Skip to content
This repository was archived by the owner on Dec 26, 2023. It is now read-only.

Commit 40a8dc6

Browse files
committed
first commit
0 parents  commit 40a8dc6

7 files changed

Lines changed: 1835 additions & 0 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/node_modules
2+
# setting.yaml

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# gcs-basic-auth

app.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
runtime: nodejs10
2+
env: standard
3+
instance_class: F1
4+
includes:
5+
- setting.yaml

index.js

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
'use strict';
2+
3+
if(process.env.STACKDRIVER_DEBUGGER === 'true'){
4+
require('@google-cloud/debug-agent').start();
5+
}
6+
7+
const request = require('request');
8+
var url = require('url');
9+
10+
const express = require('express');
11+
const app = express();
12+
13+
const basicAuthConnect = require('basic-auth-connect');
14+
15+
16+
const {Storage} = require('@google-cloud/storage');
17+
const storage = new Storage();
18+
19+
20+
// basic auth setting
21+
const basicAuth = basicAuthConnect(process.env.BASIC_AUTH_NAME, process.env.BASIC_AUTH_PASSWORD);
22+
23+
// bucket
24+
const bucket = storage.bucket(process.env.BUCKET_NAME);
25+
26+
// Google Cloud Storage generateSignedUrl Life time
27+
const GCS_URL_LIFETIME = parseInt(process.env.GCS_URL_LIFETIME);
28+
29+
//transfer option
30+
const TRANSFER_MODE = process.env.TRANSFER_MODE;
31+
const ALLOW_DIRECT_LIST = JSON.parse(process.env.ALLOW_DIRECT_LIST);
32+
const ALLOW_REDIRECT_LIST = JSON.parse(process.env.ALLOW_REDIRECT_LIST);
33+
34+
// default page
35+
const DEFAULT_HTML = process.env.DEFAULT_PAGE;
36+
// 404 page
37+
const NOT_FOUND_HTML = process.env.NOT_FOUND_PAGE;
38+
39+
40+
41+
42+
// Constants
43+
const REDIRECT = 'REDIRECT';
44+
const SIGNEDURL = 'SIGNEDURL';
45+
const FILE_NOT_FOUND = 'FILE_NOT_FOUND';
46+
47+
48+
49+
/**
50+
* file exists check
51+
*
52+
* return bool true=file exist
53+
*/
54+
async function checkFileExists(filename) {
55+
56+
const [exists] = await bucket
57+
.file(filename)
58+
.exists()
59+
.catch(err => {
60+
throw err;
61+
});
62+
63+
64+
return exists;
65+
}
66+
67+
68+
/**
69+
* Google Cloud Storage Generate Signerate URL
70+
*
71+
* @param {string} filepath
72+
* @return {string} Signerate URL
73+
*/
74+
async function generateSignedUrl(filepath) {
75+
76+
const options = {
77+
action: 'read',
78+
expires: Date.now() + GCS_URL_LIFETIME,
79+
};
80+
81+
// Get a signed URL for the file
82+
const [url] = await bucket
83+
.file(filepath)
84+
.getSignedUrl(options);
85+
86+
87+
return url;
88+
}
89+
90+
91+
async function fileSearch(url_parse) {
92+
93+
let path_name = url_parse.pathname;
94+
95+
if(path_name.slice(-1) === '/'){
96+
path_name = path_name.slice(0, -1);// remove '/'
97+
}
98+
99+
100+
let is_file = false;//file find flg
101+
102+
if(path_name !== ''){
103+
is_file = await checkFileExists(path_name);//file check
104+
}
105+
106+
107+
if( is_file === false ){//file not found
108+
109+
110+
if( await checkFileExists( `${path_name}/${DEFAULT_HTML}`) ){//check defalut html
111+
is_file = true;
112+
path_name = `${path_name}/${DEFAULT_HTML}`;
113+
}
114+
115+
116+
if(is_file === false){//defalut html not found
117+
118+
if( await checkFileExists(`/${NOT_FOUND_HTML}`) ){// check 404 html
119+
is_file = true;
120+
path_name = `/${NOT_FOUND_HTML}`;
121+
}else{
122+
return [FILE_NOT_FOUND, ''];
123+
}
124+
}
125+
}
126+
127+
128+
let file_signed_url = await generateSignedUrl(path_name);
129+
130+
if(TRANSFER_MODE === 'ALL_DIRECT'){
131+
132+
return [SIGNEDURL, file_signed_url];
133+
134+
}else{
135+
136+
const file_split_ext = path_name.split('.');
137+
if(file_split_ext.length > 0 ){
138+
const file_ext = file_split_ext[file_split_ext.length-1].toLowerCase();
139+
140+
if(TRANSFER_MODE === 'ALLOW_DIRECT' && ALLOW_DIRECT_LIST.indexOf(file_ext) >= 0){
141+
142+
return [SIGNEDURL, file_signed_url];//target transfer files
143+
144+
}else if(TRANSFER_MODE === 'ALLOW_REDIRECT' && ALLOW_REDIRECT_LIST.indexOf(file_ext) === -1){
145+
146+
return [SIGNEDURL, file_signed_url];//target transfer files
147+
}
148+
}
149+
}
150+
151+
152+
153+
//redirect path
154+
if(url_parse.query){//check get param
155+
file_signed_url = file_signed_url + '?' + url_parse.query;
156+
}
157+
158+
return [REDIRECT, file_signed_url];
159+
}
160+
161+
162+
163+
164+
165+
/**
166+
* helath check
167+
*/
168+
app.get('/_ah/start', (req, res) => {
169+
170+
res.send('I am alive.');
171+
172+
});
173+
174+
175+
176+
/**
177+
* main url listener
178+
*/
179+
app.get('/*', basicAuth, (req, res) => {
180+
181+
const url_parse = url.parse(req.url);
182+
183+
184+
fileSearch(url_parse).then(result => {
185+
186+
const [result_status, result_url] = result;
187+
188+
if(result_status === REDIRECT){
189+
190+
res.redirect(result_url);
191+
192+
}else if(result_status === SIGNEDURL){
193+
194+
const proxyRequestHeaders = Object.assign({}, req.headers);
195+
for(let key of ['host', 'authorization', 'cookie']){
196+
if(key in proxyRequestHeaders){
197+
delete proxyRequestHeaders[key];
198+
}
199+
}
200+
201+
request({
202+
url: result_url,
203+
method: req.method,
204+
headers: proxyRequestHeaders,
205+
}).pipe(res);
206+
207+
}else if(result_status === FILE_NOT_FOUND){
208+
209+
res.status(404).end('404 Not Found');
210+
}else{
211+
//It will never reach this code
212+
res.status(500).end('500 Internal Server Error');
213+
}
214+
215+
});
216+
217+
218+
});
219+
220+
221+
/**
222+
* server start
223+
*/
224+
const server = app.listen(8080);

0 commit comments

Comments
 (0)