Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pkgs/ok_http: JNIgen fixes and added WebSocket support #1257

Merged
merged 29 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
dbf7d1d
ok_http: upgrade jni and regenerate bindings
Anikate-De Jun 30, 2024
bd97d77
ok_http: jnigen fixes
Anikate-De Jun 30, 2024
4cb89e8
generate bindings for okhttp websocket classes
Anikate-De Jul 1, 2024
daf5d3a
add websocket dependency
Anikate-De Jul 4, 2024
87f7595
create proxy and interceptor; generate bindings
Anikate-De Jul 4, 2024
dc6984b
first websocket impl
Anikate-De Jul 4, 2024
78b6637
create an example section for websocket demo
Anikate-De Jul 4, 2024
7b93fb0
add integration tests
Anikate-De Jul 4, 2024
bb68b2b
add helper comments and docs to kotlin files
Anikate-De Jul 7, 2024
5cea12b
add more docs
Anikate-De Jul 7, 2024
3c14e5d
Squashed commit of the following:
Anikate-De Jul 7, 2024
91c9378
add more and more docs
Anikate-De Jul 7, 2024
9968a76
update changelog
Anikate-De Jul 7, 2024
84cd97b
Merge branch 'master' into okhttp_websockets
Anikate-De Jul 7, 2024
add63c5
Revert "ok_http: jnigen fixes"
Anikate-De Jul 7, 2024
8a22001
Merge branch 'okhttp_websockets' of https://github.com/Anikate-De/htt…
Anikate-De Jul 7, 2024
280b727
jnigen fixes
Anikate-De Jul 7, 2024
1f8de0c
fix duplicate sections in the readme
Anikate-De Jul 7, 2024
6e64458
minor text fixes
Anikate-De Jul 7, 2024
0bd1a73
fix JArray extensions
Anikate-De Jul 14, 2024
4efbfad
remove websocket example
Anikate-De Jul 14, 2024
b2711bd
fix ok_http_web_socket.dart nits
Anikate-De Jul 14, 2024
d0d1961
rename 'WSInterceptor' to 'WebSocketInterceptor'
Anikate-De Jul 14, 2024
7bc6d26
refer to deadlock issue in package: jni
Anikate-De Jul 14, 2024
8871562
added usage notes to readme and docs
Anikate-De Jul 14, 2024
57fe25f
documentation improvements
Anikate-De Jul 15, 2024
05400b5
bump up version from `0.1.0-wip` to `0.1.0`
Anikate-De Jul 15, 2024
1d0ef4c
increase step `test` timeout to 1200s to prevent workflow failures
Anikate-De Jul 15, 2024
260c2a2
upgrade jni versions and regenerate bindings
Anikate-De Jul 16, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/okhttp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,4 @@ jobs:
# - pkgs/ok_http/example/android/app/build.gradle
api-level: 21
arch: x86_64
script: cd pkgs/ok_http/example && flutter test --timeout=120s integration_test/
script: cd pkgs/ok_http/example && flutter test --timeout=1200s integration_test/
3 changes: 2 additions & 1 deletion pkgs/ok_http/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 0.1.0-wip
## 0.1.0

- Implementation of [`BaseClient`](https://pub.dev/documentation/http/latest/http/BaseClient-class.html) and `send()` method using [`enqueue()` API](https://square.github.io/okhttp/5.x/okhttp/okhttp3/-call/enqueue.html)
- `ok_http` can now send asynchronous requests and stream response bodies.
- Add [DevTools Network View](https://docs.flutter.dev/tools/devtools/network) support.
- WebSockets support is now available in the `ok_http` package. Wraps around the OkHttp [WebSocket API](https://square.github.io/okhttp/5.x/okhttp/okhttp3/-web-socket/index.html).
34 changes: 32 additions & 2 deletions pkgs/ok_http/README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[![pub package](https://img.shields.io/pub/v/cronet_http.svg)](https://pub.dev/packages/ok_http)
[![pub package](https://img.shields.io/pub/v/ok_http.svg)](https://pub.dev/packages/ok_http)
[![package publisher](https://img.shields.io/pub/publisher/ok_http.svg)](https://pub.dev/packages/ok_http/publisher)

An Android Flutter plugin that provides access to the
[OkHttp][] HTTP client.
[OkHttp][] HTTP client and the OkHttp [WebSocket][] API.

## Why use `package:ok_http`?

Expand All @@ -23,6 +23,35 @@ This size of the [example application][] APK file using different packages:
[^2]: Embeds the Cronet HTTP library.
[^3]: Accessed through [`IOClient`](https://pub.dev/documentation/http/latest/io_client/IOClient-class.html).

### 🔌 Supports WebSockets out of the box

`package:ok_http` wraps the OkHttp [WebSocket][] API which supports:

- Configured System Proxy on Android
- HTTP/2

**Example Usage of `OkHttpWebSocket`:**

```dart
Anikate-De marked this conversation as resolved.
Show resolved Hide resolved
import 'package:ok_http/ok_http.dart';
Anikate-De marked this conversation as resolved.
Show resolved Hide resolved
import 'package:web_socket/web_socket.dart';
void main() async {
final socket = await OkHttpWebSocket.connect(
Uri.parse('wss://ws.postman-echo.com/raw'));
socket.events.listen((e) async {
switch (e) {
case TextDataReceived(text: final text):
print('Received Text: $text');
await socket.close();
case BinaryDataReceived(data: final data):
print('Received Binary: $data');
case CloseReceived(code: final code, reason: final reason):
print('Connection to server closed: $code [$reason]');
}
});
}
```

## Status: experimental

**NOTE**: This package is currently experimental and published under the
Expand All @@ -41,3 +70,4 @@ feedback, suggestions, and comments, please file an issue in the
[example application]: https://github.com/dart-lang/http/tree/master/pkgs/flutter_http_example
[OkHttp]: https://square.github.io/okhttp/
[Google Play Services]: https://developers.google.com/android/guides/overview
[WebSocket]: https://square.github.io/okhttp/5.x/okhttp/okhttp3/-web-socket/index.html
5 changes: 0 additions & 5 deletions pkgs/ok_http/analysis_options.yaml

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.example.ok_http

import okhttp3.Interceptor
import okhttp3.OkHttpClient

/**
* Usage of `chain.proceed(...)` via JNI Bindings leads to threading issues. This is a workaround
* to intercept the response before it is parsed by the WebSocketReader, to prevent response parsing errors.
*
* https://github.com/dart-lang/native/issues/1337
*/
class WebSocketInterceptor {
companion object {
fun addWSInterceptor(
clientBuilder: OkHttpClient.Builder
): OkHttpClient.Builder {
return clientBuilder.addInterceptor(Interceptor { chain ->
val request = chain.request()
val response = chain.proceed(request)

response.newBuilder()
// Removing this header to ensure that OkHttp does not fail due to unexpected values.
.removeHeader("sec-websocket-extensions")
// Adding the header to ensure successful parsing of the response.
.addHeader("sec-websocket-extensions", "permessage-deflate").build()
})
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

package com.example.ok_http

import okhttp3.Response
import okhttp3.WebSocket
import okhttp3.WebSocketListener
import okio.ByteString

/**
* `OkHttp` expects a subclass of the abstract class [`WebSocketListener`](https://square.github.io/okhttp/5.x/okhttp/okhttp3/-web-socket-listener/index.html)
* to be passed to the `newWebSocket` method.
*
* `package:jnigen` does not support the ability to subclass abstract Java classes in Dart
* (see https://github.com/dart-lang/jnigen/issues/348).
*
* This file provides an interface `WebSocketListener`, which can
* be implemented in Dart and a wrapper class `WebSocketListenerProxy`, which
* can be passed to the OkHttp API.
*/
class WebSocketListenerProxy(private val listener: WebSocketListener) : WebSocketListener() {
interface WebSocketListener {
fun onOpen(webSocket: WebSocket, response: Response)
fun onMessage(webSocket: WebSocket, text: String)
fun onMessage(webSocket: WebSocket, bytes: ByteString)
fun onClosing(webSocket: WebSocket, code: Int, reason: String)
fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?)
}

override fun onOpen(webSocket: WebSocket, response: Response) {
listener.onOpen(webSocket, response)
}

override fun onMessage(webSocket: WebSocket, text: String) {
listener.onMessage(webSocket, text)
}

override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
listener.onMessage(webSocket, bytes)
}

override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
listener.onClosing(webSocket, code, reason)
}

override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
listener.onFailure(webSocket, t, response)
}
}
10 changes: 10 additions & 0 deletions pkgs/ok_http/example/integration_test/web_socket_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:ok_http/ok_http.dart';
import 'package:web_socket_conformance_tests/web_socket_conformance_tests.dart';

void main() {
testAll(OkHttpWebSocket.connect);
}
3 changes: 3 additions & 0 deletions pkgs/ok_http/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ dependencies:
ok_http:
path: ../
provider: ^6.1.1
web_socket: ^0.1.5

dev_dependencies:
dart_flutter_team_lints: ^3.0.0
Expand All @@ -27,6 +28,8 @@ dev_dependencies:
integration_test:
sdk: flutter
test: ^1.23.1
web_socket_conformance_tests:
path: ../../web_socket_conformance_tests/

flutter:
uses-material-design: true
21 changes: 21 additions & 0 deletions pkgs/ok_http/jnigen.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,16 @@ classes:
- "okhttp3.Callback"
- "okhttp3.ConnectionPool"
- "okhttp3.Dispatcher"
- "java.util.concurrent.ExecutorService"
- "okhttp3.Cache"
- "com.example.ok_http.RedirectReceivedCallback"
- "com.example.ok_http.RedirectInterceptor"
- "com.example.ok_http.AsyncInputStreamReader"
- "com.example.ok_http.DataCallback"
- "okhttp3.WebSocket"
- "com.example.ok_http.WebSocketListenerProxy"
- "okio.ByteString"
- "com.example.ok_http.WebSocketInterceptor"

# Exclude the deprecated methods listed below
# They cause syntax errors during the `dart format` step of JNIGen.
Expand Down Expand Up @@ -86,3 +91,19 @@ exclude:
- "okhttp3.Headers#-deprecated_size"
- "okhttp3.Dispatcher#-deprecated_executorService"
- "okhttp3.Cache#-deprecated_directory"
- "java.util.concurrent.ExecutorService#invokeAll"
- "java.util.concurrent.ExecutorService#invokeAny"
- "java.util.concurrent.ExecutorService#submit"
- "okio.ByteString$Companion#-deprecated_getByte"
- "okio.ByteString$Companion#-deprecated_size"
- 'okio.ByteString\$Companion#-deprecated_decodeBase64'
- 'okio.ByteString\$Companion#-deprecated_decodeHex'
- 'okio.ByteString\$Companion#-deprecated_encodeString'
- 'okio.ByteString\$Companion#-deprecated_encodeUtf8'
- 'okio.ByteString\$Companion#-deprecated_of'
- 'okio.ByteString\$Companion#-deprecated_read'
- "okio.ByteString#-deprecated_getByte"
- "okio.ByteString#-deprecated_size"

preamble: |
// ignore_for_file: prefer_expression_function_bodies
5 changes: 4 additions & 1 deletion pkgs/ok_http/lib/ok_http.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
// BSD-style license that can be found in the LICENSE file.

/// An Android Flutter plugin that provides access to the
/// [OkHttp](https://square.github.io/okhttp/) HTTP client.
/// [OkHttp](https://square.github.io/okhttp/) HTTP client, and the OkHttp
/// [WebSocket](https://square.github.io/okhttp/5.x/okhttp/okhttp3/-web-socket/index.html)
/// API
///
/// ```
/// import 'package:ok_http/ok_http.dart';
Expand Down Expand Up @@ -53,3 +55,4 @@ import 'package:http/http.dart';
import 'src/ok_http_client.dart';

export 'src/ok_http_client.dart';
export 'src/ok_http_web_socket.dart';
Loading