Skip to content

Commit

Permalink
Merge pull request #1318 from dart-lang/merge-http2-package
Browse files Browse the repository at this point in the history
Merge `package:http2`
  • Loading branch information
mosuem authored Oct 18, 2024
2 parents 92d317a + e6f2fb5 commit 5e2281e
Show file tree
Hide file tree
Showing 68 changed files with 11,204 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/http2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
name: "package:http2"
about: "Create a bug or file a feature request against package:http2."
labels: "package:http2"
---
4 changes: 4 additions & 0 deletions .github/labeler.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
- changed-files:
- any-glob-to-any-file: 'pkgs/http/**'

'package:http2':
- changed-files:
- any-glob-to-any-file: 'pkgs/http2/**'

'package:http_parser':
- changed-files:
- any-glob-to-any-file: 'pkgs/http_parser/**'
Expand Down
70 changes: 70 additions & 0 deletions .github/workflows/http2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: package:http2

on:
push:
branches:
- master
paths:
- '.github/workflows/http2.yaml'
- 'pkgs/http2/**'
pull_request:
paths:
- '.github/workflows/http2.yaml'
- 'pkgs/http2/**'
schedule:
- cron: "0 0 * * 0"

defaults:
run:
working-directory: pkgs/http2/

env:
PUB_ENVIRONMENT: bot.github

jobs:
# Check code formatting and static analysis on a single OS (linux)
# against Dart dev.
analyze:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
sdk: [dev]
steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938
- uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672
with:
sdk: ${{ matrix.sdk }}
- id: install
name: Install dependencies
run: dart pub get
- name: Check formatting
run: dart format --output=none --set-exit-if-changed .
if: always() && steps.install.outcome == 'success'
- name: Analyze code
run: dart analyze --fatal-infos
if: always() && steps.install.outcome == 'success'

# Run tests on a matrix consisting of two dimensions:
# 1. OS: ubuntu-latest, (macos-latest, windows-latest)
# 2. release channel: dev
test:
needs: analyze
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# Add macos-latest and/or windows-latest if relevant for this package.
os: [ubuntu-latest]
sdk: [3.2, dev]
steps:
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938
- uses: dart-lang/setup-dart@0a8a0fc875eb934c15d08629302413c671d3f672
with:
sdk: ${{ matrix.sdk }}
- id: install
name: Install dependencies
run: dart pub get
- name: Run VM tests
run: dart test --platform vm
if: always() && steps.install.outcome == 'success'
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and the browser.
| [cupertino_http](pkgs/cupertino_http/) | A macOS/iOS Flutter plugin that provides access to the [Foundation URL Loading System](https://developer.apple.com/documentation/foundation/url_loading_system). | [![pub package](https://img.shields.io/pub/v/cupertino_http.svg)](https://pub.dev/packages/cupertino_http) |
| [flutter_http_example](pkgs/flutter_http_example/) | An Flutter app that demonstrates how to configure and use `package:http`. ||
| [http](pkgs/http/) | A composable, multi-platform, Future-based API for HTTP requests. | [![pub package](https://img.shields.io/pub/v/http.svg)](https://pub.dev/packages/http) |
| [http2](pkgs/http2/) | A HTTP/2 implementation in Dart. | [![pub package](https://img.shields.io/pub/v/http2.svg)](https://pub.dev/packages/http2) |
| [http_client_conformance_tests](pkgs/http_client_conformance_tests/) | A library that tests whether implementations of package:http's `Client` class behave as expected. | |
| [http_parser](pkgs/http_parser/) | A platform-independent package for parsing and serializing HTTP formats. | [![pub package](https://img.shields.io/pub/v/http_parser.svg)](https://pub.dev/packages/http_parser) |
| [http_profile](pkgs/http_profile/) | A library used by HTTP client authors to integrate with the DevTools Network View. | [![pub package](https://img.shields.io/pub/v/http_profile.svg)](https://pub.dev/packages/http_profile) |
Expand Down
4 changes: 4 additions & 0 deletions pkgs/http2/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Don’t commit the following directories created by pub.
.dart_tool
.packages
pubspec.lock
5 changes: 5 additions & 0 deletions pkgs/http2/.test_config
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"test_package": {
"platforms" : ["vm"]
}
}
8 changes: 8 additions & 0 deletions pkgs/http2/AUTHORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Below is a list of people and organizations that have contributed
# to the project. Names should be added to the list like so:
#
# Name/Organization <email address>

Google Inc. <*@google.com>

Alexandre Ardhuin <[email protected]>
115 changes: 115 additions & 0 deletions pkgs/http2/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
## 2.3.1

- Require Dart 3.2
- Add topics to `pubspec.yaml`
- Move to `dart-lang/http` monorepo.

## 2.3.0

- Only send updates on frames and pings being received when there are listeners, as to not fill up memory.

## 2.2.0

- Transform headers to lowercase.
- Expose pings to connection to enable the KEEPALIVE feature for gRPC.

## 2.1.0

- Require Dart `3.0.0`
- Require Dart `2.17.0`.
- Send `WINDOW_UPDATE` frames for the connection to account for data being sent on closed streams until the `RST_STREAM` has been processed.

## 2.0.1

- Simplify the implementation of `MultiProtocolHttpServer.close`.
- Require Dart `2.15.0`.

## 2.0.0

* Migrate to null safety.

## 1.0.1

* Add `TransportConnection.onInitialPeerSettingsReceived` which fires when
initial SETTINGS frame is received from the peer.

## 1.0.0

* Graduate package to 1.0.
* `package:http2/http2.dart` now reexports `package:http2/transport.dart`.

## 0.1.9

* Discard messages incoming after stream cancellation.

## 0.1.8+2

* On connection termination, try to dispatch existing messages, thereby avoiding
terminating existing streams.

* Fix `ClientTransportConnection.isOpen` to return `false` if we have exhausted
the number of max-concurrent-streams.

## 0.1.8+1

* Switch all uppercase constants from `dart:convert` to lowercase.

## 0.1.8

* More changes required for making tests pass under Dart 2.0 runtime.
* Modify sdk constraint to require '>=2.0.0-dev.40.0'.

## 0.1.7

* Fixes for Dart 2.0.

## 0.1.6

* Strong mode fixes and other cleanup.

## 0.1.5

* Removed use of new `Function` syntax, since it isn't fully supported in Dart
1.24.

## 0.1.4

* Added an `onActiveStateChanged` callback to `Connection`, which is invoked when
the connection changes state from idle to active or from active to idle. This
can be used to implement an idle connection timeout.

## 0.1.3

* Fixed a bug where a closed window would not open correctly due to an increase
in initial window size.

## 0.1.2

* The endStream bit is now set on the requested frame, instead of on an empty
data frame following it.
* Added an `onTerminated` hook that is called when a TransportStream receives
a RST_STREAM frame.

## 0.1.1+2

* Add errorCode to exception toString message.

## 0.1.1+1

* Fixing a performance issue in case the underlying socket is not writeable
* Allow clients of MultiProtocolHttpServer to supply [http.ServerSettings]
* Allow the draft version 'h2-14' in the ALPN protocol negogiation.

## 0.1.1

* Adding support for MultiProtocolHttpServer in the
`package:http2/multiprotocol_server.dart` library

## 0.1.0

* First version of a HTTP/2 transport implementation in the
`package:http2/transport.dart` library

## 0.0.1

- Initial version
27 changes: 27 additions & 0 deletions pkgs/http2/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
Copyright 2015, the Dart project authors.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:

* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
* Neither the name of Google LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55 changes: 55 additions & 0 deletions pkgs/http2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[![pub package](https://img.shields.io/pub/v/http2.svg)](https://pub.dev/packages/http2)
[![package publisher](https://img.shields.io/pub/publisher/http2.svg)](https://pub.dev/packages/http2/publisher)

This library provides an http/2 interface on top of a bidirectional stream of bytes.

## Usage

Here is a minimal example of connecting to a http/2 capable server, requesting
a resource and iterating over the response.

```dart
import 'dart:convert';
import 'dart:io';
import 'package:http2/http2.dart';
Future<void> main() async {
final uri = Uri.parse('https://www.google.com/');
final transport = ClientTransportConnection.viaSocket(
await SecureSocket.connect(
uri.host,
uri.port,
supportedProtocols: ['h2'],
),
);
final stream = transport.makeRequest(
[
Header.ascii(':method', 'GET'),
Header.ascii(':path', uri.path),
Header.ascii(':scheme', uri.scheme),
Header.ascii(':authority', uri.host),
],
endStream: true,
);
await for (var message in stream.incomingMessages) {
if (message is HeadersStreamMessage) {
for (var header in message.headers) {
final name = utf8.decode(header.name);
final value = utf8.decode(header.value);
print('Header: $name: $value');
}
} else if (message is DataStreamMessage) {
// Use [message.bytes] (but respect 'content-encoding' header)
}
}
await transport.finish();
}
```

An example with better error handling is available [here][example].

See the [API docs][api] for more details.
9 changes: 9 additions & 0 deletions pkgs/http2/analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# https://dart.dev/tools/analysis#the-analysis-options-file
include: package:dart_flutter_team_lints/analysis_options.yaml

analyzer:
language:
strict-casts: true
errors:
# Disabled as there are several dozen violations.
constant_identifier_names: ignore
2 changes: 2 additions & 0 deletions pkgs/http2/dart_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
tags:
flaky: # Tests that should be run as a separate job on Travis
67 changes: 67 additions & 0 deletions pkgs/http2/example/display_headers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:http2/transport.dart';

void main(List<String> args) async {
if (args.length != 1) {
print('Usage: dart display_headers.dart <HTTPS_URI>');
exit(1);
}

var uriArg = args[0];

if (!uriArg.startsWith('https://')) {
print('URI must start with https://');
exit(1);
}

var uri = Uri.parse(uriArg);

var socket = await connect(uri);

// The default client settings will disable server pushes. We
// therefore do not need to deal with [stream.peerPushes].
var transport = ClientTransportConnection.viaSocket(socket);

var headers = [
Header.ascii(':method', 'GET'),
Header.ascii(':path', uri.path),
Header.ascii(':scheme', uri.scheme),
Header.ascii(':authority', uri.host),
];

var stream = transport.makeRequest(headers, endStream: true);
await for (var message in stream.incomingMessages) {
if (message is HeadersStreamMessage) {
for (var header in message.headers) {
var name = utf8.decode(header.name);
var value = utf8.decode(header.value);
print('$name: $value');
}
} else if (message is DataStreamMessage) {
// Use [message.bytes] (but respect 'content-encoding' header)
}
}
await transport.finish();
}

Future<Socket> connect(Uri uri) async {
var useSSL = uri.scheme == 'https';
if (useSSL) {
var secureSocket = await SecureSocket.connect(uri.host, uri.port,
supportedProtocols: ['h2']);
if (secureSocket.selectedProtocol != 'h2') {
throw Exception('Failed to negogiate http/2 via alpn. Maybe server '
"doesn't support http/2.");
}
return secureSocket;
} else {
return await Socket.connect(uri.host, uri.port);
}
}
Loading

0 comments on commit 5e2281e

Please sign in to comment.