Express Deprecated - express

I have a photo app that uploads photos to AWS. When testing the uploading photos feature on my localhost, my terminal throws the following error:
express deprecated res.send(status, body): Use
res.status(status).send(body) instead aws/aws.js:50:18
My photos DO save to AWS, im just wondering what this error is and how to fix it. Below is my aws code that the error refers too.
'use strict';
var AWS = require('aws-sdk'),
crypto = require('crypto'),
config = require('./aws.json'),
createS3Policy,
getExpiryTime;
getExpiryTime = function () {
var _date = new Date();
return '' + (_date.getFullYear()) + '-' + (_date.getMonth() + 1) + '-' +
(_date.getDate() + 1) + 'T' + (_date.getHours() + 3) + ':' + '00:00.000Z';
};
createS3Policy = function(contentType, callback) {
var date = new Date();
var s3Policy = {
'expiration': getExpiryTime(),
'conditions': [
['starts-with', '$key', 'images/'],
{'bucket': config.bucket},
{'acl': 'public-read'},
['starts-with', '$Content-Type', contentType],
{'success_action_status' : '201'}
]
};
// stringify and encode the policy
var stringPolicy = JSON.stringify(s3Policy);
var base64Policy = new Buffer(stringPolicy, 'utf-8').toString('base64');
// sign the base64 encoded policy
var signature = crypto.createHmac('sha1', config.secretAccessKey)
.update(new Buffer(base64Policy, 'utf-8')).digest('base64');
// build the results object
var s3Credentials = {
s3Policy: base64Policy,
s3Signature: signature,
AWSAccessKeyId: config.accessKeyId
};
// send it back
callback(s3Credentials);
};
exports.getS3Policy = function(req, res) {
createS3Policy(req.query.mimeType, function (creds, err) {
if (!err) {
return res.send(200, creds);
} else {
return res.send(500, err);
}
});
};

Replace res.send(statusCode, "something") with res.status(statusCode).send("something")
This should do it for your code:
exports.getS3Policy = function(req, res) {
createS3Policy(req.query.mimeType, function (creds, err) {
if (!err) {
return res.send(creds); //200 is not needed here, express will default to this
} else {
return res.status(500).send(err);
}
});
};

Related

Cloudflare ESI worker / TypeError: Body has already been used

I'm trying to use a CloudFlare worker to manage my backend ESI fragments but i get an error:
Uncaught (in promise) TypeError: Body has already been used. It can only be used once. Use tee() first if you need to read it twice.
Uncaught (in response) TypeError: Body has already been used. It can only be used once. Use tee() first if you need to read it twice.
I don't find where the body has already been used
The process is:
get a response with the parts
Transform the body by replacing parts fragments with sub Backend calls (streamTransformBody function)
return the response
addEventListener("fetch", event => {
event.respondWith(handleRequest(event.request))
});
const esiHeaders = {
"user-agent": "cloudflare"
}
async function handleRequest(request) {
// get cookies from the request
if(cookie = request.headers.get("Cookie")) {
esiHeaders["Cookie"] = cookie
console.log(cookie)
}
// Clone the request so that it's no longer immutable
newRequest = new Request(request)
// remove cookie from request
newRequest.headers.delete('Cookie')
// Add header to get <esi>
newRequest.headers.set("Surrogate-Capability", "abc=ESI/1.0")
console.log(newRequest.url);
const response = await fetch(newRequest);
let contentType = response.headers.get('content-type')
if (!contentType || !contentType.startsWith("text/")) {
return response
}
// Clone the response so that it's no longer immutable
const newResponse = new Response(response.body, response);
let { readable, writable } = new TransformStream()
streamTransformBody(newResponse.body, writable)
newResponse.headers.append('x-workers-hello', 'Hello from
Cloudflare Workers');
return newResponse;
}
async function streamTransformBody(readable, writable) {
const startTag = "<".charCodeAt(0);
const endTag = ">".charCodeAt(0);
let reader = readable.getReader();
let writer = writable.getWriter();
let templateChunks = null;
while (true) {
let { done, value } = await reader.read();
if (done) break;
while (value.byteLength > 0) {
if (templateChunks) {
let end = value.indexOf(endTag);
if (end === -1) {
templateChunks.push(value);
break;
} else {
templateChunks.push(value.subarray(0, end));
await writer.write(await translate(templateChunks));
templateChunks = null;
value = value.subarray(end + 1);
}
}
let start = value.indexOf(startTag);
if (start === -1) {
await writer.write(value);
break;
} else {
await writer.write(value.subarray(0, start));
value = value.subarray(start + 1);
templateChunks = [];
}
}
}
await writer.close();
}
async function translate(chunks) {
const decoder = new TextDecoder();
let templateKey = chunks.reduce(
(accumulator, chunk) =>
accumulator + decoder.decode(chunk, { stream: true }),
""
);
templateKey += decoder.decode();
return handleTemplate(new TextEncoder(), templateKey);
}
async function handleTemplate(encoder, templateKey) {
const linkRegex = /(esi:include.*src="(.*?)".*\/)/gm
let result = linkRegex.exec(templateKey);
let esi
if (!result) {
return encoder.encode(`<${templateKey}>`);
}
if (result[2]) {
esi = await subRequests(result[2]);
}
return encoder.encode(
`${esi}`
);
}
async function subRequests(target){
target = esiHost + target
const init = {
method: 'GET',
headers: esiHeaders
}
let response = await fetch(target, init)
if (!response.ok) {
return ''
}
let text = await response.text()
return '<!--esi-->' + text + '<!--/esi-->'
}

Upload large file to Azure blob storage via REST API Put Block Blob

I am using React Native to build Mobile application for Andrioid and iOS.
based on the situation that no framework is exist to support Azure Storage API for React Native (all frameworks are required browsers that does not exist in React Native),
I use REST API for the interaction with the Azure storage and it works fine e.g list containers, list blob, get blob and put blob.
in order to upload large file I tried to use the same mechanizm for 'put block' api (as describe here: https://learn.microsoft.com/en-us/rest/api/storageservices/put-block) without succcess, failed on error code 403.
I will appreciate for your assist.
Thank you.
my code for upload single block:
private createAuthorizationHeader(canonicalizedString: string) {
const str = CryptoJS.HmacSHA256(canonicalizedString, CryptoJS.enc.Base64.parse(this.config.accountKey));
const sig = CryptoJS.enc.Base64.stringify(str);
const authorizationHeader = `SharedKey ${this.config.accountName}:${sig}`;
return authorizationHeader;
}
async putBlockBlob(containerName: str, blobPath: str, blobContent: str, blockIndex: number,) {
const requestMethod = 'PUT';
const urlPath = `${containerName}/${blobPath}`;
const dateInRfc1123Format = new Date(Date.now()).toUTCString();
const storageServiceVersion = '2019-12-12';
const blobLength: number = blobContent.length;
const blockId = Buffer.from(`block-${blockIndex}`).toString('base64');
const blobType = 'BlockBlob';
// StringToSign =
// VERB + "\n" +
// Content-Encoding + "\n" +
// Content-Language + "\n" +
// Content-Length + "\n" +
// Content-MD5 + "\n" +
// Content-Type + "\n" +
// Date + "\n" +
// If-Modified-Since + "\n" +
// If-Match + "\n" +
// If-None-Match + "\n" +
// If-Unmodified-Since + "\n" +
// Range + "\n" +
// CanonicalizedHeaders +
// CanonicalizedResource;
const canonicalizedHeaders = `x-ms-date:${dateInRfc1123Format}\nx-ms-version:${storageServiceVersion}`;
const canonicalizedResource = `/${this.config.accountName}/${urlPath}}\nblockid:${blockId}\ncomp:block`;
const stringToSign = `${requestMethod}\n\n\n${blobLength}\n\napplication/octet-stream\n\n\n\n\n\n\n${canonicalizedHeaders}\n${canonicalizedResource}`;
const uriStr = `${urlPath}?comp=block&blockid=${blockId}`;
const authorizationHeader = this.createAuthorizationHeader(stringToSign);
const header = {
'cache-control': 'no-cache',
'x-ms-date': dateInRfc1123Format,
'x-ms-version': storageServiceVersion,
Authorization: authorizationHeader,
'Content-Length': `${blobLength}`,
'Content-Type': 'application/octet-stream',
};
try {
return axios
.create({baseURL: `https://${this.config.accountName}.blob.core.windows.net/`,})
.request({
method: requestMethod,
url: uriStr,
data: blobContent,
headers: header,
})
.then((response) => response.data)
.catch((err) => {
throw err;
});
} catch (err) {
console.log(err);
throw err;
}
}
I believe the issue is coming because of a missing new line character between Range and CanonicalizedHeaders.
Can you try by changing the following line of code:
const stringToSign = `${requestMethod}\n\n\n${blobLength}\n\napplication/octet-stream\n\n\n\n\n\n\n${canonicalizedHeaders}\n${canonicalizedResource}`;
to:
const stringToSign = `${requestMethod}\n\n\n${blobLength}\n\napplication/octet-stream\n\n\n\n\n\n\n\n${canonicalizedHeaders}\n${canonicalizedResource}`;
it will help you to upload the data to Azure storage server
upload file to Server
export const uploadMedia = async (params: any, callBack: any) => {
const SAS_URL: any = "https://${blobUrl}.blob.core.windows.net";
const CONTAINER: any = "";
const SAS_TOKEN: any = "";
const { fileType, localUri } = params;
const userId = "set user ID here";
const fileName = String(fileType).concat(customIdGenerator(7));
const assetPath = `${SAS_URL}/${CONTAINER}/${userId}/${fileName}`;
HEADER["x-ms-blob-content-type"] = CONST_HEADER(fileType);
return await RNFetchBlob.fetch(
"PUT",
`${assetPath}?${SAS_TOKEN}`,
HEADER,
RNFetchBlob.wrap(localUri)
)
?.uploadProgress(callBack)
.then(() => {
return assetPath;
});
};
fileType = 'video' | image | pdf
let params: any = {
fileType: 'image',
localUri: image,
};
generate Custom Id for Uniqueness or you can also use UUID
const customIdGenerator = (length: any) => {
var result = "";
var characters =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var charactersLength = characters.length;
for (var i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return result;
};
set Headers for different Files
const CONST_HEADER = (type: any) => {
return type == 'image'
? `image/png`
: type == 'video'
? 'video/mp4'
: type == 'pdf' && 'application/pdf';
};

Sharp image uploader not working when running app with PM2

I have an express app that I am using Sharp to resize images after a user has uploaded them. When I start the app using 'npm start' I am able to upload the images with no issues, but if I use PM2 to manage the process the images don't get saved on the server. I can save them without using Sharp to resize them, it is only when I have the code for sharp that they don't get saved. Below is the code from my controller. Multer is processing the form and sharp is resizing the image.
doNewRecipe: function(req, res) {
for (var key in req.body) {
req.body[key] = req.body[key] || undefined;
}
var body = _.pick(req.body, 'title', 'description', 'ingredients', 'instructions', 'yield', 'prep_time', 'cook_time', 'categoryId');
body.userId = req.session.user.id;
if (req.file) {
var tempPath = req.file.path,
ext = path.extname(req.file.originalname).toLowerCase(),
//targetPath = path.resolve(finalUploadPath + req.file.filename + ext);
targetPath = path.resolve(finalUploadPath);
fs.renameSync(tempPath, tempPath + ext);
var newFileName = req.file.filename + ext;
var imageFile = tempPath + ext;
body.image = newFileName;
sharp(imageFile)
.resize(450, 450)
.max()
.toFile('./public/finalUpload/' + newFileName, function(err, info) {
body.image = newFileName;
fs.unlinkSync(path.resolve(tempPath + ext));
db.recipe.create(body).then(function(recipe) {
res.redirect('/recipe/view/' + recipe.id);
}, function(e) {
console.log(e.message);
res.render('error', {message: e.toString()});
});
});
//fs.renameSync(tempPath, targetPath);
} else {
db.recipe.create(body).then(function(recipe) {
res.redirect('/recipe/view/' + recipe.id);
}, function(e) {
console.log(e.message);
res.render('error', {message: e.toString()});
});
}
},
If you use path to determine where to save the file it will transport easily from one system to another. I actually created a few variables to determine where to save the file. Below is my code.
if (process.env.NODE_ENV === 'production') {
var finalUploadPath = 'hidden';
var googleTracking = true;
} else if (process.env.NODE_ENV === 'staging') {
var finalUploadPath = 'hidden';
var googleTracking = false;
} else {
var finalUploadPath = 'hidden';
var googleTracking = false;
}
sharp(imageFile)
.resize(450, 450)
.max()
.toFile(finalUploadPath + req.file.filename + '.jpg', function(err, info) {
body.image = req.file.filename + '.jpg';
fs.unlinkSync(path.resolve(tempPath + ext));
compressAndResize(path.resolve(__dirname, '../public/finalUpload/' + body.image));
db.recipe.create(body).then(function(recipe) {
req.flash('success', 'Recipe created');
res.redirect('/recipe/view/' + recipe.id + '/' + recipe.slug);
}, function(e) {
console.log(e.message);
req.flash('error', 'Error creating new recipe');
res.render('error', {message: e.toString(), csrfToken: req.csrfToken(), google: googleTracking});
});
});

Custom Authentication Azure Mobile Services by Api

I am creating a custom authentication via API on Azure Mobile Service, and picked based on this answer:
Registering and login users in Azure Mobile Services
Then joined with the code of the previous link to create the authentication token.
But I get "internal server error" when I invoke the API. The error happens in here: "...results.length..."
var crypto = require('crypto');
var iterations = 1000;
var bytes = 32;
var aud = "Custom";
var masterKey = "wkeHEoWUaPJSHsSOcWgmVLOZbIpeeg92";
var _request;
var _response;
exports.post = function(request, response) {
var user = request.body.userName;
var pass = request.body.password;
_request = request;
_response = response
validateUserNamePassword(user, pass, function(error, userId, token) {
if (error) {
response.send(401, { error: "Unauthorized" });
} else {
response.send(200, { user: userId, token: token });
}
});
}
function validateUserNamePassword(user, pass, funcao){
var accounts = _request.service.tables.getTable('account');
accounts
.where({ userid : user })
.read({
success: function(results)
{
if (results.length === 0)
{
_response.send(401, { error: "Unauthorized1" });
console.log("Incorrect username or password");
_request.respond(401, "Incorrect username or password");
}
else
_response.send(401, { error: "Unauthorized2" });
var account = results[0];
hash(item.password, account.salt, function(err, h) {
var incoming = h;
if (slowEquals(incoming, account.password)) {
var expiry = new Date().setUTCDate(new Date().getUTCDate() + 30);
var userId = aud + ":" + account.id;
_request.respond(200, {
userId: userId,
token: zumoJwt(expiry, aud, userId, masterKey)
});
}
else {
_request.respond(401, "Incorrect username or password");
}
});
}
}
});
}
function hash(text, salt, callback) {
crypto.pbkdf2(text, salt, iterations, bytes, function(err, derivedKey){
if (err) { callback(err); }
else {
var h = new Buffer(derivedKey).toString('base64');
callback(null, h);
}
});
}
function slowEquals(a, b) {
var diff = a.length ^ b.length;
for (var i = 0; i < a.length && i < b.length; i++) {
diff |= (a[i] ^ b[i]);
}
return diff === 0;
}
function zumoJwt(expiryDate, aud, userId, masterKey) {
var crypto = require('crypto');
function base64(input) {
return new Buffer(input, 'utf8').toString('base64');
}
function urlFriendly(b64) {
return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(new RegExp("=", "g"), '');
}
function signature(input) {
var key = crypto.createHash('sha256').update(masterKey + "JWTSig").digest('binary');
var str = crypto.createHmac('sha256', key).update(input).digest('base64');
return urlFriendly(str);
}
var s1 = '{"alg":"HS256","typ":"JWT","kid":0}';
var j2 = {
"exp":expiryDate.valueOf() / 1000,
"iss":"urn:microsoft:windows-azure:zumo",
"ver":1,
"aud":aud,
"uid":userId
};
var s2 = JSON.stringify(j2);
var b1 = urlFriendly(base64(s1));
var b2 = urlFriendly(base64(s2));
var b3 = signature(b1 + "." + b2);
return [b1,b2,b3].join(".");
}
I'm invoking like this:
try
{
var loginInput = new JObject();
loginInput.Add("userName", "breno");
loginInput.Add("password", "test");
var loginResult = await LoginAuthenticationService.InvokeApiAsync("login", loginInput);
LoginAuthenticationService.CurrentUser = new MobileServiceUser((string)loginResult["user"]);
LoginAuthenticationService.CurrentUser.MobileServiceAuthenticationToken = (string)loginResult["token"];
}
catch (MobileServiceInvalidOperationException e)
{
var exception = e;
}
If you're getting this error "Failed to load script file 'login.js': SyntaxError: Unexpected token }" as seen in the comments, there is a syntax issue with your script. You'll need to go through your scripts and figure out where the issue is at.

Can I get the failed request id when PhantomJS get resource error?

I don't quite understand why PhantomJS only returns the url of request for onResourceError callback, while for the other two resource callbacks it returns the request id. That makes "finding which request did actually fail" really impossible if there is more than one request to the same url. Does anyone knows how to get the failed request id?
Actually, that's just old documentation. onResourceError has the id of a failed request.
page.onResourceError = function(resourceError) {
console.log('Unable to load resource (request ID:' + resourceError.id + 'URL:' + resourceError.url + ')');
console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
};
Why do you really need to request id ?
Since onResourceError was added in 1.9, some information may be missing.
A way to resolve your problem is to keep in an array all requested resourcessuach as in netsniff example.
Here is a very basic implementation :
var page = require('webpage').create(),
system = require('system');
if (system.args.length === 1) {
console.log('Usage: netsniff.js <some URL>');
phantom.exit(1);
} else {
page.address = system.args[1];
page.resources = [];
page.onLoadStarted = function () {
page.startTime = new Date();
};
page.onResourceRequested = function (req) {
page.resources[req.id] = {
request: req,
startReply: null,
endReply: null
};
};
page.onResourceReceived = function (res) {
if (res.stage === 'start') {
page.resources[res.id].startReply = res;
}
if (res.stage === 'end') {
page.resources[res.id].endReply = res;
}
};
page.onResourceError = function(resourceError) {
console.log('Unable to load resource (URL:' + resourceError.url + ')');
console.log('Error code: ' + resourceError.errorCode + '. Description: ' + resourceError.errorString);
page.resources.forEach(function (resource) {
var request = resource.request,
endReply = resource.endReply;
if (request && request.url === resourceError.url && !endReply) {
console.log('request id was :' + request.id);
}
})
};
page.open(page.address, function (status) {
var har;
if (status !== 'success') {
console.log('FAIL to load the address');
phantom.exit(1);
} else {
page.endTime = new Date();
page.title = page.evaluate(function () {
return document.title;
});
console.log(page.title);
phantom.exit();
}
});
}
onResourceError, you just need to find first/last/all recorded urls that match the error resource url.