NodeJS - Google 云存储签名 URL 的 CORS 问题
NodeJS - CORS issue with Google Cloud Storage Signed URLs
我想让艺术家客户使用 Signed URLs 将图像上传到云存储。
以下后端脚本用于获取签名 url,它位于 Google 云负载平衡器之后:
(那个(负载均衡器)有什么影响吗?)
exports.getSignedUrl = async (req, res) => {
if (req.method !== 'POST') {
// Return a "method not allowed" error
return res.status(405).end();
}
try {
console.log("Getting signed url..");
const storage = new Storage();
const bucketName = 'bucket' in req.body ? req.body.bucket : 'gsk-public';
// Get a reference to the destination file in GCS
const file = storage.bucket(bucketName).file(req.body.filename);
// Create a temporary upload URL
const expiresAtMs = 'expires' in req.body ? req.body.expires : Date.now() + 100; // Link expires in 1 minute
const configuration = {
version: 'v4',
action: req.body.action,
expires: expiresAtMs
};
if ('type' in req.body) {
configuration.contentType = req.body.type;
}
console.log("Got signed url!");
const url = await file.getSignedUrl(configuration);
console.log(url);
return res.send(url[0]);
}
catch (err) {
console.error(err);
return res.status(500).end();
}
};
CORS 设置:
[
{
"origin": [
"https://localhost:3000/",
"https://dreamlouvre-git-development-samuq.vercel.app/"
],
"responseHeader": "*",
"method": ["GET", "PUT", "POST", "OPTIONS", "HEAD"],
"maxAgeSeconds": 3600
}
]
Next.js API 获取签名的端点 url:
import axios from 'axios';
import {config} from '../config';
import { fileTypeToJPG, createQueryString } from '../../../helpers/helpers';
import mime from 'mime';
export default async (req, res) => {
if(req.method === 'POST'){
try{
if(!config.mimeExtensions.some(el => el===mime.getExtension(req.body.type))){
//throw new Error('The file type of your image is not supported. Following types are supported: jpg, png, bmp and tiff.');
return res.status(500).json({ statusCode: 500, message: 'Unsupported filetype.' });
}
//console.log('file name: ', req.body.filename);
//console.log('auth header: ', req.headers.authorization);
const response = await axios.post(`${config.apiBaseUrl}/auth/signedUrl`, req.body, {headers:{"authorization": `Bearer ${req.headers.authorization}`}});
//console.log("Respdata");
//console.log(response.data);
//console.log(response.data[0]);
const respData = {
filename: fileTypeToJPG(req.body.filename),
originalFileName: req.body.filename,
url: response.data
};
return res.status(200).json(respData);
}catch (err) {
//console.log(err);
return res.status('status' in err ? err.status : 500).json({ statusCode: 500, message: err.message });
}
}
else return res.status(403);
};
Next.js 要签名的前端代码 url:
const badi = {
type: file.type,
filename: fileName,
action: "write",
bucket: config.bucketOriginal,
};
console.log("upload 3");
const resp = await axios.post(`/api/auth/getSignedUrl`, badi, {
headers: { authorization: token },
});
console.log("upload 4", resp.data);
await axios.put(resp.data.url, file, {
headers: { "Content-type": file.type },
});
观察到的行为: 访问已被 CORS 策略阻止。
控制台日志 upload 4
和已签名的 url,但已签名的 url 不起作用。
预期行为: put 请求将正常工作。
可能导致 CORS 错误的到期时间错误。
我修复了这个:
const expiresAtMs = 'expires' in req.body ? req.body.expires : Date.now() + 100;
对此:
const expiresAtMs = 'expires' in req.body ? req.body.expires : Date.now() + 15*60*1000;
编辑:代码已经开始工作,但现在抛出 403 错误,声称存在格式错误的 content-type header 尽管实际上没有。 Content-type header 出现在请求中。
我想让艺术家客户使用 Signed URLs 将图像上传到云存储。
以下后端脚本用于获取签名 url,它位于 Google 云负载平衡器之后:
(那个(负载均衡器)有什么影响吗?)
exports.getSignedUrl = async (req, res) => {
if (req.method !== 'POST') {
// Return a "method not allowed" error
return res.status(405).end();
}
try {
console.log("Getting signed url..");
const storage = new Storage();
const bucketName = 'bucket' in req.body ? req.body.bucket : 'gsk-public';
// Get a reference to the destination file in GCS
const file = storage.bucket(bucketName).file(req.body.filename);
// Create a temporary upload URL
const expiresAtMs = 'expires' in req.body ? req.body.expires : Date.now() + 100; // Link expires in 1 minute
const configuration = {
version: 'v4',
action: req.body.action,
expires: expiresAtMs
};
if ('type' in req.body) {
configuration.contentType = req.body.type;
}
console.log("Got signed url!");
const url = await file.getSignedUrl(configuration);
console.log(url);
return res.send(url[0]);
}
catch (err) {
console.error(err);
return res.status(500).end();
}
};
CORS 设置:
[
{
"origin": [
"https://localhost:3000/",
"https://dreamlouvre-git-development-samuq.vercel.app/"
],
"responseHeader": "*",
"method": ["GET", "PUT", "POST", "OPTIONS", "HEAD"],
"maxAgeSeconds": 3600
}
]
Next.js API 获取签名的端点 url:
import axios from 'axios';
import {config} from '../config';
import { fileTypeToJPG, createQueryString } from '../../../helpers/helpers';
import mime from 'mime';
export default async (req, res) => {
if(req.method === 'POST'){
try{
if(!config.mimeExtensions.some(el => el===mime.getExtension(req.body.type))){
//throw new Error('The file type of your image is not supported. Following types are supported: jpg, png, bmp and tiff.');
return res.status(500).json({ statusCode: 500, message: 'Unsupported filetype.' });
}
//console.log('file name: ', req.body.filename);
//console.log('auth header: ', req.headers.authorization);
const response = await axios.post(`${config.apiBaseUrl}/auth/signedUrl`, req.body, {headers:{"authorization": `Bearer ${req.headers.authorization}`}});
//console.log("Respdata");
//console.log(response.data);
//console.log(response.data[0]);
const respData = {
filename: fileTypeToJPG(req.body.filename),
originalFileName: req.body.filename,
url: response.data
};
return res.status(200).json(respData);
}catch (err) {
//console.log(err);
return res.status('status' in err ? err.status : 500).json({ statusCode: 500, message: err.message });
}
}
else return res.status(403);
};
Next.js 要签名的前端代码 url:
const badi = {
type: file.type,
filename: fileName,
action: "write",
bucket: config.bucketOriginal,
};
console.log("upload 3");
const resp = await axios.post(`/api/auth/getSignedUrl`, badi, {
headers: { authorization: token },
});
console.log("upload 4", resp.data);
await axios.put(resp.data.url, file, {
headers: { "Content-type": file.type },
});
观察到的行为: 访问已被 CORS 策略阻止。 控制台日志
upload 4
和已签名的 url,但已签名的 url 不起作用。预期行为: put 请求将正常工作。
可能导致 CORS 错误的到期时间错误。 我修复了这个:
const expiresAtMs = 'expires' in req.body ? req.body.expires : Date.now() + 100;
对此:
const expiresAtMs = 'expires' in req.body ? req.body.expires : Date.now() + 15*60*1000;
编辑:代码已经开始工作,但现在抛出 403 错误,声称存在格式错误的 content-type header 尽管实际上没有。 Content-type header 出现在请求中。