Increase sails bodyP - file-upload

In my app (sails 0.12.0) I want to extend a limit of bytes send upon POST request. So I've followed the comments in this stackoverflow question
var skipper = require('skipper');
skipper.limit = 1024*1024*100;
middleware: {
bodyParser: skipper
}
I still get an error:
"data": {
"code": "E_EXCEEDS_UPLOAD_LIMIT",
"name": "Upload Error",
"maxBytes": 15000000,
"written": 15007474,
"message": "Upload limit of 15000000 bytes exceeded (15007474 bytes written)"
}
I've also tried to add the code below directly under module.exports.http and then I've tried to add it in the middleware only.
bodyParser: (function () {
var opts = {limit:'50mb'};
var fn;
// Default to built-in bodyParser:
fn = require('skipper');
return fn(opts);
})
My question is: Why none of these codes work and how can I increase the limit. The solution can be not elegant.

Everything that you need - set
maxBytes
attribute in object of options to upload() method of skipper Upstream.
req.file('image').upload({maxBytes: 50000000}, function (err, uploadedFiles) {
if (err) return res.serverError(err.message);
if(uploadedFiles.length > 0) {
// do with uploaded images what you want
.....
}
});

Related

Whatsapp Web - how to access data now?

It used to be possible to access http://web.whatsapp.com/ with the Store object in JavaScript. A few hours ago, this stopped working. How does it update chat data now? It must save the data somewhere.
I'm using this to get the Store again:
setTimeout(function() {
// Returns promise that resolves to all installed modules
function getAllModules() {
return new Promise((resolve) => {
const id = _.uniqueId("fakeModule_");
window["webpackJsonp"](
[],
{
[id]: function(module, exports, __webpack_require__) {
resolve(__webpack_require__.c);
}
},
[id]
);
});
}
var modules = getAllModules()._value;
// Automatically locate modules
for (var key in modules) {
if (modules[key].exports) {
if (modules[key].exports.default) {
if (modules[key].exports.default.Wap) {
store_id = modules[key].id.replace(/"/g, '"');
}
}
}
}
}, 5000);
function _requireById(id) {
return webpackJsonp([], null, [id]);
}
// Module IDs
var store_id = 0;
var Store = {};
function init() {
Store = _requireById(store_id).default;
console.log("Store is ready" + Store);
}
setTimeout(function() {
init();
}, 7000);
Just copy&paste on the console and wait for the message "Store is ready".
Enjoy!
To explain Pablo's answer in detail, initially we load all the Webpack modules using code based on this How do I require() from the console using webpack?.
Essentially, the getAllModules() returns a promise with all the installed modules in Webpack. Each module can be required by ID using the _requireById(id) which uses the webpackJsonp(...) function that is exposed by Webpack.
Once the modules are loaded, we need to identify which id corresponds to the Store. We search for a module containing exports.default.Wap and assign it's id as the Store ID.
You can find more details on my github wiki here
A faster method:
I grab the source of the "app" and find the store object then
I save it in ZStore global variable. :D
!function(){for(var t of document.getElementsByTagName("script"))t.src.indexOf("/app.")>0&&fetch(t.src,{method:"get"}).then(function(t){return t.text().then(function(t){var e=t.indexOf('var a={};t["default"]')-89;window.ZStore=window.webpackJsonp([],null,JSON.stringify(t.substr(e,10))).default})})}();
window.ZStore will contain the object.
Non minified version:
(function() {
function getStore(url) {
fetch(url, {
"method": 'get'
}).then(function(response) {
return response.text().then(function(data) {
var offset = data.indexOf('var a={};t["default"]') - 89;
window.ZStore = window.webpackJsonp([], null, JSON.stringify(data.substr(offset, 10))).default
});
});
}
for (var e of document.getElementsByTagName("script")) {
if (e.src.indexOf("/app.") > 0) getStore(e.src);
}
})();

Internationalization ( i18n ) for express-validator

Is it possible to get messages returned by express-validator into a language other than english for internationalization (i18n) ?
I tried looking into the source code and I could not find it.
express-validator
Thanks
It's probably something you have to create yourself, but it shouldn't be too hard.
When you assign an error message with withMessage() you can send more than just a single string. You can for example send an object. So you can put the error messages, for all the languages, for a particular error, in an object.
Here is an example:
Route:
const countValidation = require('./count.validation');
router
.route('/blogposts')
.get(
countValidation.count,
blogpostController.blogpostsGetAll,
);
Validator (in a separate file called count.validation.js):
const message = {
english: 'count must be between 1 and 1000',
chinese: 'count must be between 1 and 1000, but in chinese',
};
module.exports.count = [
check('count')
.optional()
.isInt({ min: 1, max: 1000 })
.withMessage(message)
];
This response will be sent when validation fails:
{
"errors": {
"count": {
"location": "query",
"param": "count",
"value": "-1",
"msg": {
"english": "count must be between 1 and 1000",
"chinese": "count must be between 1 and 1000, but in chinese"
}
}
}
}
In this particular example the front-end has to choose what error message to display depending on user settings or user agent.
It's also possible to deal with what error message to use on the server side, if we know what language the client is using from the request. We could for example read the accept-language header in the request. Here is an example of how that could be done:
The controller function:
Rather than using this (standard handling of errors, almost straight from the readme):
module.exports.blogpostsGetAll = (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.mapped() });
}
// The rest of the function...
};
we use this:
module.exports.blogpostsGetAll = (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
const errorsInProperLanguage = handleLanguages(req.headers, errors.mapped());
return res.status(422).json({ errors: errorsInProperLanguage });
}
// The rest of the function...
};
Example function to only use one language:
function handleLanguages(headers, errorsMapped) {
const language = headers['accept-language'].split(',')[0];
for (let errorKey in errorsMapped) {
errorsMapped[errorKey].msg = errorsMapped[errorKey].msg[language];
}
return errorsMapped;
}
Because the accept-language header contains language codes, not language names, we have to modify the message object slightly:
const message = {
'en-US': 'count must be between 1 and 1000',
'zh-CH': 'count must be between 1 and 1000, but in chinese',
};
The message object HAS to contain the first language code in the accept-language header for this to work. The handleLanguage function doesn't handle errors. It's only an example to show how it could be done; don't use it directly.
The error message would change to
{
"errors": {
"count": {
"location": "query",
"param": "count",
"value": "-1",
"msg": "count must be between 1 and 1000, but in chinese"
}
}
}
when the first language in accept-language is zh-CH.
This is now possible with express-validator v5.0.0.
If you pass withMessage() a function, it will be called with the field value, the request, its location and its path.
Example from the docs:
check('something').isInt().withMessage((value, { req, location, path }) => {
return req.translate('validation.message.path', { value, location, path });
}),

API Automation - Is it possible to get response of the post call

I'm learning how to automate API with frisby.js on gmail.api.
I want to create a test where I create and delete(or send) a Draft message.
So I wrote a test which creates a Draft and my question is - can I write a code that gets at least ID of generated response from my Post call?
var frisby = require('frisby');
frisby.create('Create Draft Google')
.post('https://www.googleapis.com/gmail/v1/users/me/drafts?access_token=*my-token-here*', {
message: {
raw: "RGFuJ3MgVG9vbHMgYXJlIGNvb2wh",
id: "1547265285486966899"
}
}, { json: true })
.inspectJSON()
.inspectBody()
.expectStatus(200)
.toss();
So, to clarify, I want to write another part of THIS^ test with
.after(function(err, res, body){}
Steps:
I create a Draft message
I want my test to automatically get ID of just created Draft
So I could Delete it\Send it
Thanks!
When you create a draft, you will get the id of the newly created draft in the response:
Request
POST https://www.googleapis.com/gmail/v1/users/me/drafts?access_token={access_token}
{
"message": {
"raw": "RnJ..."
}
}
Response
{
"id": "r5019331921817638435",
"message": {
"id": "157948187e41b5bb",
"threadId": "157948187e41b5bb",
"labelIds": [
"DRAFT"
]
}
}
Then you can use this id to either send or delete the message.
.afterJSON(function(json){
callback(json.id);
})
I used this function and it worked. Thanks to my friend for help :D
Here're full tests if someone needs it:
This is how I get an ID of created Draft
var frisby = require('frisby');
var new_id = function(frisby, callback)
{
frisby.create('Create Draft Google')
.post('https://www.googleapis.com/gmail/v1/users/me/drafts?access_token=[my_token]', {
message: {
raw: "RGFu...",
}
}, { json: true })
.inspectJSON()
.inspectBody()
.expectStatus(200)
.afterJSON(function(json){
callback(json.id);
})
.toss();
};
module.exports = new_id;
This is how I used it to delete this Draft
var frisby = require('frisby');
var getid_spec = require("./getid_spec.js");
getid_spec(frisby,function(id){
frisby.create('Delete Google Draft Test')
.delete("https://www.googleapis.com/gmail/v1/users/me/drafts/" +id +"?access_token=[my_token]", {})
.expectStatus(204)
.toss();
})

Angular2 - Multiple dependent sequential http api calls

I am building an Angular2 app and one of the components needs to make multiple API calls which are dependent on the previous ones.
I currently have a service which makes an API call to get a list of TV shows. For each show, I then need to call a different API multiple times to step through the structure to determine if the show exists on a Plex server.
The API documentation is here
For each show, I need to make the following calls and get the correct data to determine if it exists: (Assume we have variables <TVShow>, <Season>, <Episode>)
http://baseURL/library/sections/?X-Plex-Token=xyz will tell me:
title="TV Shows" key="2"
http://baseURL/library/sections/2/all?X-Plex-Token=xyz&title=<TVShow> will tell me: key="/library/metadata/2622/children"
http://baseURL/library/metadata/2622/children?X-Plex-Token=xyz will tell me: index="<Season>" key="/library/metadata/14365/children"
http://baseURL/library/metadata/14365/children?X-Plex-Token=xyz will tell me: index="<Episode>" which implies that the episode I have exists.
The responses are in json, I have removed a lot of the excess text. At each stage I need to check that the right fields exist (<TVShow>, <Season>, <Episode>) so that they can be used for the next call. If not, I need to return that the show does not exist. If it does, I will probably want to return an id for the show.
I have looked at lots of examples including promise, async & flatmap, but am not sure how to solve this based on the other examples I have seen.
How to chain Http calls in Angular2
Angular 2.0 And Http
Angular 2 - What to do when an Http request depends on result of another Http request
Angular 2 chained Http Get Requests with Iterable Array
nodejs async: multiple dependant HTTP API calls
How to gather the result of Web APIs on nodeJS with 'request' and 'async'
Here is what I have for getting the list of shows. (shows.service.ts)
export class ShowsHttpService {
getShows(): Observable<Show[]> {
let shows$ = this._http
.get(this._showHistoryUrl)
.map(mapShows)
.catch(this.handleError);
return shows$;
}
}
function mapShows(response:Response): Show[] {
return response.json().data.map(toShow);
}
function toShow(r:any): Show {
let show = <Show>({
episode: r.episode,
show_name: r.show_name,
season: r.season,
available : false, // I need to fill in this variable if the show is available when querying the Plex API mentioned above.
});
// My best guess is here would be the right spot to call the Plex API as we are dealing with a single show at a time at this point, but I cannot see how.
return show;
}
Here is the relevant code from the component (shows.component.ts)
public getShows():any {
this._ShowsHttpService
.getShows()
.subscribe(w => this.shows = w);
console.log(this.shows);
}
Bonus points
Here are the obvious next questions that are interesting, but not necessary:
The first API query will be much faster than waiting for all of the other queries to take place (4 queries * ~10 shows). Can the initial list be returned and then updated with the available status when it is ready.
The first Plex call to get the key="2" only needs to be performed once. It could be hard coded, but instead, can it be performmed once and remembered?
Is there a way to reduce the number of API calls? I can see that I could remove the show filter, and search through the results on the client, but this doesn't seam ideal either.
The 4 calls for each show must be done sequentially, but each show can be queried in parallel for speed. Is this achievable?
Any thoughts would be much appreciated!
Not sure if I totally understand your question, but here is what I do:
I make the first http call, then when the subscribe fires, it calls completeLogin. I could then fire another http call with its own complete function and repeat the chain.
Here is the component code. The user has filled in the login information and pressed login:
onSubmit() {
console.log(' in on submit');
this.localUser.email = this.loginForm.controls["email"].value;
this.localUser.password = this.loginForm.controls["password"].value;
this.loginMessage = "";
this.checkUserValidation();
}
checkUserValidation() {
this.loginService.getLoggedIn()
.subscribe(loggedIn => {
console.log("in logged in user validation")
if(loggedIn.error != null || loggedIn.error != undefined || loggedIn.error != "") {
this.loginMessage = loggedIn.error;
}
});
this.loginService.validateUser(this.localUser);
}
This calls the loginservice ValidateUser method
validateUser(localUser: LocalUser) {
this.errorMessage = "";
this.email.email = localUser.email;
var parm = "validate~~~" + localUser.email + "/"
var creds = JSON.stringify(this.email);
var headers = new Headers();
headers.append("content-type", this.constants.jsonContentType);
console.log("making call to validate");
this.http.post(this.constants.taskLocalUrl + parm, { headers: headers })
.map((response: Response) => {
console.log("json = " + response.json());
var res = response.json();
var result = <AdminResponseObject>response.json();
console.log(" result: " + result);
return result;
})
.subscribe(
aro => {
this.aro = aro
},
error => {
console.log("in error");
var errorObject = JSON.parse(error._body);
this.errorMessage = errorObject.error_description;
console.log(this.errorMessage);
},
() => this.completeValidateUser(localUser));
console.log("done with post");
}
completeValidateUser(localUser: LocalUser) {
if (this.aro != undefined) {
if (this.aro.errorMessage != null && this.aro.errorMessage != "") {
console.log("aro err " + this.aro.errorMessage);
this.setLoggedIn({ email: localUser.email, password: localUser.password, error: this.aro.errorMessage });
} else {
console.log("log in user");
this.loginUser(localUser);
}
} else {
this.router.navigate(['/verify']);
}
}
In my login service I make a call to the authorization service which returns an observable of token.
loginUser(localUser: LocalUser) {
this.auth.loginUser(localUser)
.subscribe(
token => {
console.log('token = ' + token)
this.token = token
},
error => {
var errorObject = JSON.parse(error._body);
this.errorMessage = errorObject.error_description;
console.log(this.errorMessage);
this.setLoggedIn({ email: "", password: "", error: this.errorMessage });
},
() => this.completeLogin(localUser));
}
In the authorization service:
loginUser(localUser: LocalUser): Observable<Token> {
var email = localUser.email;
var password = localUser.password;
var headers = new Headers();
headers.append("content-type", this.constants.formEncodedContentType);
var creds:string = this.constants.grantString + email + this.constants.passwordString + password;
return this.http.post(this.constants.tokenLocalUrl, creds, { headers: headers })
.map(res => res.json())
}
The point here in this code, is to first call the validateUser method of the login service, upon response, based on the return information, if its valid, I call the loginUser method on the login service. This chain could continue as long as you need it to. You can set class level variables to hold the information that you need in each method of the chain to make decisions on what to do next.
Notice also that you can subscribe to the return in the service and process it there, it doesn't have to return to the component.
Okay, Here goes:
public getShows():any {
this._ShowsHttpService
.getShows()
.subscribe(
w => this.shows = w,
error => this.errorMessage = error,
() => this.completeGetShows());
}
completeGetShow() {
//any logic here to deal with previous get;
this.http.get#2()
.subscribe(
w => this.??? = w),
error => this.error = error,
() => this.completeGet#2);
}
completeGet#2() {
//any logic here to deal with previous get;
this.http.get#3()
.subscribe(
w => this.??? = w),
error => this.error = error,
() => this.completeGet#3);
}
completeGet#3() {
//any logic here to deal with previous get;
//another http: call like above to infinity....
}

PDF Blob is not showing content, Angular 2

I have problem very similar to this PDF Blob - Pop up window not showing content, but I am using Angular 2. The response on question was to set responseType to arrayBuffer, but it not works in Angular 2, the error is the reponseType does not exist in type RequestOptionsArgs. I also tried to extend it by BrowserXhr, but still not work (https://github.com/angular/http/issues/83).
My code is:
createPDF(customerServiceId: string) {
console.log("Sending GET on " + this.getPDFUrl + "/" + customerServiceId);
this._http.get(this.getPDFUrl + '/' + customerServiceId).subscribe(
(data) => {
this.handleResponse(data);
});
}
And the handleResponse method:
handleResponse(data: any) {
console.log("[Receipt service] GET PDF byte array " + JSON.stringify(data));
var file = new Blob([data._body], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
}
I also tried to saveAs method from FileSaver.js, but it is the same problem, pdf opens, but the content is not displayed. Thanks
I had a lot of problems with downloading and showing content of PDF, I probably wasted a day or two to fix it, so I'll post working example of how to successfully download PDF or open it in new tab:
myService.ts
downloadPDF(): any {
return this._http.get(url, { responseType: ResponseContentType.Blob }).map(
(res) => {
return new Blob([res.blob()], { type: 'application/pdf' })
}
}
myComponent.ts
this.myService.downloadPDF().subscribe(
(res) => {
saveAs(res, "myPDF.pdf"); //if you want to save it - you need file-saver for this : https://www.npmjs.com/package/file-saver
var fileURL = URL.createObjectURL(res);
window.open(fileURL); / if you want to open it in new tab
}
);
NOTE
It is also worth mentioning that if you are extending Http class to add headers to all your requests or something like that, it can also create problems for downloading PDF because you will override RequestOptions, which is where we add responseType: ResponseContentType.Blob and this will get you The request body isn't either a blob or an array buffer error.
ANGULAR 5
I had the same problem which I lost few days on that.
Here my answer may help others, which helped to render pdf.
For me even though if i mention as responseType : 'arraybuffer', it was unable to take it.
For that you need to mention as responseType : 'arraybuffer' as 'json'.(Reference)
Working code
downloadPDF(): any {
return this._http.get(url, { responseType: 'blob' as 'json' }).subscribe((res) => {
var file = new Blob([res], { type: 'application/pdf' });
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
}
}
Referred from the below link
https://github.com/angular/angular/issues/18586
Amit,
You can rename the filename by adding a variable to the end of the string
so saveAs(res, "myPDF.pdf");
Becomes
saveAs(res, "myPDF_"+someVariable+".pdf");
where someVariable might be a counter or my personal favorite a date time string.
This worked for me
var req = this.getPreviewPDFRequest(fd);
this.postData(environment.previewPDFRFR, req).then(res => {
res.blob().then(blob => {
console.clear();
console.log(req);
console.log(JSON.stringify(req));
const fileURL = URL.createObjectURL(blob);
window.open(fileURL, '', 'height=650,width=840');
})
});
Server side (Java/Jetty) : REST service that returns a File Response
The File Response itself will automatically be parsed into a pdf blob file by Jetty (because of the annotation #Produces("application/pdf") ), in other to be send to and read by the web client
#GET
#Path("/download-pdf/{id}")
#Produces("application/pdf")
public Response downloadPDF(#ApiParam(value = "Id of the report record")
#PathParam("id") Long id) {
ResponseBuilder response = null;
try {
PDFReportService service = new PDFReportService();
File reportFile = service.getPDFReportFile(id);
response = Response.ok((Object) reportFile);
response.header("Content-Disposition","attachment; filename="+reportFile.getName());
return response.build();
} catch (DomainException e) {
response = Response.serverError().entity("server.error");
}
return response.build();
}
Client side code (angular 2) : grab the blob and print it in a new browser tab
The key is to insure that you read the request reponse as a blob (as the server returned a blob; in my case)
Now, I tried so hard but I finally figured out that Angular 2 has not implemented any function to handle blob responses (neither res['_body'], nor res.blob() worked for me)
So I found no other workaround than using JQuery ajax to perform that file blob request, like following:
public downloadPDFFile() {
let fileURL = serverURL+"/download-pdf/"+id;
let userToken: string = your_token;
showWaitingLoader();
$.ajax({
url: fileURL,
cache: false,
headers: {
"Content-Type": "application/json",
"Authorization": "Basic " + userToken
},
xhrFields: {
responseType: 'blob' //Most important : configure the response type as a blob
},
success: function(blobFile) {
const url = window.URL.createObjectURL(blobFile);
window.open(url);
stopWaitingLoader();
},
error: function(e){
console.log("DOWNLOAD ERROR :", e);
}
});
}