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

Partial Download does not include range header (null value) #462

Closed
JeanNicolasdeLamballerie opened this issue Oct 28, 2022 · 16 comments · Fixed by #468
Closed

Partial Download does not include range header (null value) #462

JeanNicolasdeLamballerie opened this issue Oct 28, 2022 · 16 comments · Fixed by #468
Labels

Comments

@JeanNicolasdeLamballerie

Hello guys ! Before anything, I'd like to preface this by saying it might be an error in implementation from my part; if this is the case I have misunderstood how the flow of the drive API works. I have tried getting help on Stackoverflow, but no one ever answered my post.

Here's my issue :

I am creating a small application based on audio files stored on Google Drive, in Flutter.

I am using the drive api to make my requests, with these scopes in my google sign in :

GoogleSignIn _googleSignIn = GoogleSignIn(
  scopes: [
    'email',
    'https://www.googleapis.com/auth/userinfo.profile',
    'https://www.googleapis.com/auth/contacts.readonly',
    'https://www.googleapis.com/auth/drive',
    'https://www.googleapis.com/auth/docs',
    'https://www.googleapis.com/auth/drive.appdata',
  ],
);

I have an auth element and handle signing in and out. Until then, no issues.

I can also request my files with an implementation looking like this, where I implemented a passed down API instance :

  var api = widget.api.getAPI();
  var files = await api.files.list($fields: '*');

This works perfectly, and so does :

  var api = widget.api.getAPI();
  var files = await api.files.get("myFileId"); (//does get a file instance)

But since I'd like to retrieve some of the Metadata included in my audio files, and since the drive API doesn't natively support extracting audio metadata and sending it as a google metadata, I thought I'd extract it with a partial download on the file itself.

Here's the catch : I can't seem to get the partial download to work.
Based on the doc, I thought the implementation would look something like this :

import 'package:googleapis/drive/v3.dart' as ga;    
(...)
try {
            var partiallyDownloadedFile = await api.files.get(
                "myFileIdHere",
                downloadOptions: ga.PartialDownloadOptions(ga.ByteRange(0, 10))); //should get a ga.Media instance
            print("partial download succeeded");
            print(partiallyDownloadedFile);
            //(...do stuff...)
            return;
          } catch (err) {
            print('Error occured : ');
            print(err);
            return;
          }

But this always throws this error :

ApiRequestError(message: Attempting partial download but got invalid
'Content-Range' header (was: null, expected: bytes 0-10/).)

I tried using it on Wav files, but also MP4 files. The error is always the same, which leads me to believe it's my implementation that's somehow wrong, but I'm not sure what I'm supposed to do to fix it. Is it my request missing the header ? The response not including it ?
While very clear, that error doesn't help me troubleshoot my issue at all. I can't seem to find any documentation on how to conduct a partial media request. I haven't found any example projects to compare it with.

PartialDownloadOptions does not have much documentation.

I could make a partial request through the download links with a homemade http request (which is how I can read the music to begin with) but the drive API supposedly allows this. Could anyone help me correct my implementation, or confirm this is a bug ?

kevmoo added a commit that referenced this issue Nov 2, 2022
@kevmoo
Copy link
Collaborator

kevmoo commented Nov 2, 2022

I tried this out – and it worked fine - #467

* Credentials expire in 0:59:38.996594 *
{
 "id": "14M5lqQutVBqb_PPYH6GT51_mX2WkbXbL",
 "kind": "drive#file",
 "mimeType": "application/octet-stream",
 "name": "Google APIs test file on 2022-11-02 15:36:25.486859"
}
properties: null
      size: 1024
11
all deleted

@kevmoo
Copy link
Collaborator

kevmoo commented Nov 2, 2022

would you include the full stack trace? That might help...

@JeanNicolasdeLamballerie
Copy link
Author

Error: ApiRequestError(message: Attempting partial download but got invalid 'Content-Range' header (was: null, expected: bytes 0-10/).) C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 266:49 throw_ packages/_discoveryapis_commons/src/api_requester.dart 114:9 request C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 45:50 <fn> C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/zone.dart 1653:54 runUnary C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 147:18 handleValue C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 766:44 handleValueCallback C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 795:13 _propagateToListeners C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 566:5 [_completeWithValue] C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/future_impl.dart 639:7 callback C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/schedule_microtask.dart 40:11 _microtaskLoop C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/async/schedule_microtask.dart 49:5 _startMicrotaskLoop C:/b/s/w/ir/cache/builder/src/out/host_debug/dart-sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart 166:15 <fn>

This is the stacktrace I get.
My dart is 2.18.2, flutter 3.3.6.
I'll try to simplify where I get the http client into the code to see if it's not me messing something up. Thanks for the help !

@kevmoo
Copy link
Collaborator

kevmoo commented Nov 3, 2022

Ah! Look at chrome console. Do you see errors/warnings about not being allowed to set certain headers? the browser controls the headers that client code can send

@JeanNicolasdeLamballerie
Copy link
Author

JeanNicolasdeLamballerie commented Nov 3, 2022

I am currently using Edge and Chrome for debugging, and it turns out to be weirder than I thought ;
Actually, the request itself completes, with the proper params :
image
image

I do even get the response :
image
I have no specific error related to headers, only a dart error popping up :
image
I haven't tested on android for now, as I upgraded this project and need to also make sure to use JDK11 first.

@kevmoo
Copy link
Collaborator

kevmoo commented Nov 3, 2022 via email

@kevmoo
Copy link
Collaborator

kevmoo commented Nov 3, 2022

@JeanNicolasdeLamballerie – could you patch in #468 and try it out?

@kevmoo
Copy link
Collaborator

kevmoo commented Nov 3, 2022

dependency_overrides:
  _discoveryapis_commons:
    git:
      url: https://github.com/google/googleapis.dart
      ref: i462_fix_header_casing
      path: discoveryapis_commons

@JeanNicolasdeLamballerie
Copy link
Author

JeanNicolasdeLamballerie commented Nov 3, 2022

Sorry @kevmoo , I was indeed struggling with my pubspec.yaml.
I've been trying to move it around, but I keep getting that same apiRequestError.
image
I ran flutter clean & flutter pub get.

@kevmoo
Copy link
Collaborator

kevmoo commented Nov 3, 2022

Check your pubspec.lock file – is it pointing at the github link?

Is the error exactly the same? Can you include it? I'd love to have line numbers with the new code...

@JeanNicolasdeLamballerie
Copy link
Author

Pubspec looks fine, and importing
import 'package:_discoveryapis_commons/_discoveryapis_commons.dart' as commons;
shows me the code including your fix.
image
I went and added a print of the headers themselves, and this was the result :
image

But I think I have an idea, because this timestamp doesn't fit the (correct) request; it fits the preflight request :
image

Could it be that preflight messing with the request() function?

@JeanNicolasdeLamballerie
Copy link
Author

Disregard this, it doesn't, I just messed up the two requests because the preflight completed after the request.
Actually, the headers in the dart code simply do not include the "content-range" at all, but are still fired with it. I have no idea where they are added.

@kevmoo
Copy link
Collaborator

kevmoo commented Nov 3, 2022

@JeanNicolasdeLamballerie
Copy link
Author

JeanNicolasdeLamballerie commented Nov 3, 2022

It might be related to the access-control-expose-header from the response not including Content-Range. I commented the error directly in the library and the request does return the proper stream in that case. I manage to get the first few bytes. Maybe the lib should use the Content-Length instead to check if the range value is correct ?

kevmoo added a commit that referenced this issue Nov 4, 2022
Remove check that cannot be done in the browser
Also remove invalid header sets for HTTP requests in the browser

Fixes #462
@kevmoo
Copy link
Collaborator

kevmoo commented Nov 4, 2022

Now it's fixed! I also checked it

@kevmoo
Copy link
Collaborator

kevmoo commented Nov 4, 2022

It might be related to the access-control-expose-header from the response not including Content-Range. I commented the error directly in the library and the request does return the proper stream in that case. I manage to get the first few bytes. Maybe the lib should use the Content-Length instead to check if the range value is correct ?

access-control-expose-header – YUP!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants