Skip to content

Instantly share code, notes, and snippets.

@userqq
Last active September 20, 2023 20:01
Show Gist options
  • Save userqq/f75875f0fe7bbf6c38b3fb8a00d3dea2 to your computer and use it in GitHub Desktop.
Save userqq/f75875f0fe7bbf6c38b3fb8a00d3dea2 to your computer and use it in GitHub Desktop.
# # # # # # # # # #
# USAGE:
#
# $accelUri = ''
# . '/' . 'internal_google_drive'
# . '/' . $google_drive_file_id
# . '/' . $filename
# . '/' . $google_drive_access_token;
# http_response_code(204);
# header('X-Accel-Redirect: ' . rawurlencode($accelUri));
#
# # # # # # # # # #
location ~* ^/internal_google_drive/(.+)/(.+)/(.*)$ {
limit_rate 1m;
# Do not allow people to mess with this location directly
# Only internal redirects are allowed
internal;
# nginx has to be able to resolve the remote URLs
resolver 8.8.8.8;
# Location-specific logging
access_log /var/log/nginx/internal_google_drive.access.log;
error_log /var/log/nginx/internal_google_drive.error.log;
# Extract download url from the request
set $download_id $1;
set $filename $2;
set $token $3;
# Compose download url
set $download_url https://www.googleapis.com/drive/v3/files/$download_id?alt=media;
# Set download request headers
proxy_set_header Authorization 'Bearer $token';
# The next two lines could be used if your storage
# backend does not support Content-Disposition
# headers used to specify file name browsers use
# when save content to the disk
proxy_hide_header Content-Disposition;
add_header Content-Disposition 'attachment; filename="$filename"';
# Do not touch local disks when proxying
# content to clients
proxy_max_temp_file_size 0;
# Download the file and send it to client
proxy_pass $download_url;
post_action @dispose;
}
location @dispose {
set $path https://127.0.0.1/dl/dispose;
proxy_method GET;
proxy_set_header Host $server_name;
proxy_pass $path;
}
@dvdblk
Copy link

dvdblk commented Apr 7, 2020

Hey. What's the purpose of this? I was trying to serve one of my gdrive folders with Nginx autoindex and came across your gist...

@userqq
Copy link
Author

userqq commented Apr 9, 2020

@dvdblk
Hi!
I was used this code to pipe Google Drive files through me server.

Not sure it is possible to make Nginx autoindex works with Google Drive since Google Drive using specific api for list folders and files.
Also you need be able to refresh access token every few hours. In my case it was handled by PHP.

Maybe it's possible to find workaround with lua-nginx or other scripting nginx modules, but you will need to implement whole logic with Google Drive by your own.

You can take a look at https://rclone.org/ and use it's own server or mount google drive via FUSE and serve mounted folder by nginx (but better use first option, FUSE is pretty slow);

@dvdblk
Copy link

dvdblk commented Apr 9, 2020

Alright :) thanks a lot! I'll take a look at rclone.

@userqq
Copy link
Author

userqq commented Apr 9, 2020

@dvdblk You are welcome :)

@ripperdoc
Copy link

Sorry, what is the location @dispose for?

@userqq
Copy link
Author

userqq commented Apr 13, 2020

@ripperdoc

I've used this location to call php script after download was finished or aborted.

proxy_set_header Host $server_name;

Means script placed on the same host

Since in my case it was Yii2 framework i've used action bound to /dl/dispose route

set $path https://127.0.0.1/dl/dispose;

If you don't need this feature you can remove whole location @dispose block and post_action @dispose; directive.

Please note as far as I know post_action is not documented and not recommended by nginx developers. Probably lua-nginx's log_by_* will be more safe and convinient.

@abdulaziz-git
Copy link

Hi @userqq
Is this configuration use server bandwith for download or not?
and how to use this?
like accessing the file, for public shared google drive download link is using this url https://www.googleapis.com/drive/v3/files/[file_ID]?alt=media&key=[YOUR API KEY]
if using this configuration, how is the url structured?
is it using POST to example.com/dl/dispose with data file_id, filename and token ?

@userqq
Copy link
Author

userqq commented Sep 20, 2021

Hi @abdulaziz-git !
This configuration is USING server bandwith and NOT USING server local storage, file is profixied directly from google drive to client.
To use this you should have fastcgi server behind nginx (like PHP or any other) which will handle authorization token rotation.

For example:

  • Client requesting http://site.com/index.php?fileId=123 which has real index.php script behing it.
  • This index.php script should decide which exactly file you want send to client and where to get authorization token.
  • Then index php responds with X-Accel-Redirect header (Please reffer to https://www.nginx.com/resources/wiki/start/topics/examples/x-accel/ for more information) and some additional data. X-Accel-Redirect header should contain path to valid nginx location.
  • Nginx will intercept fastcgi response with X-Accel-Redirect header and run new location - location from X-Accel-Redirect header, but now nginx has variables with access token and fileId.

So to sum up:

  • User requesting http://site.com/index.php?fileId=123 and receiving file directly from this URL.
  • But behind scene there processing of index.php file and internal redirect in nginx

I'm not sure there is the possibility to download file without authorization token automatically, even if it public.

Also I can suggest to use https://rclone.org/, it should be much easier to configure.

@abdulaziz-git
Copy link

Hi @userqq

Thanks for you explanation
I see so the function is same as using rclone mounting to folder and serve download through that folder

Thanks

@userqq
Copy link
Author

userqq commented Sep 21, 2021

Hi @abdulaziz-git !
As far as i know rclone able to serve files via http by itself, without mointing folder.
Please check https://rclone.org/commands/rclone_serve/

@Lucky-069
Copy link

I was looking to see if it's possible to get gindex work with ngnix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment