I am trying to alter the settings of a Sails JS app and am having a bit of bother passing a parameter to the body-Parser in order to change the default settings.
I previously had the issue described here: Posting larger files
I believe this problem has been answered correctly by changing the default 'limit' option, as a 100kb default size minus the 33% overhead from the formData object is pretty consistent with what size of file I can/can't send. So the solution proposed was this:
var bodyParser = require('body-parser');
...
app.use(bodyParser.urlencoded( { limit: 1048576 } ));
but am unable to implement the solution in my Sails app. I have read through the Sails Documentation on changing the middleware settings, and tried the following in my config/http.js file...
First attempt - wrapper
/**
* HTTP Server Settings
* (sails.config.http)
*/
module.exports.http = {
middleware: {
order: [
'startRequestTimer',
'cookieParser',
'session',
'refreshSessionCookie',
'bodyParserInit',
'bodyParser',
'handleBodyParserError',
'compress',
'methodOverride',
'poweredBy',
'$custom',
'requestLogger',
'router',
'www',
'favicon',
'404',
'500'
],
bodyParserInit : (function (){
let bodyParser = require('body-parser');
return bodyParser( { extended: true, limit: 1073741824 } )
})(),
)
},
// cache: 31557600000
};
Second attempt - overwrite
/**
* HTTP Server Settings
* (sails.config.http)
*/
module.exports.http = {
middleware: {
order: [
'startRequestTimer',
'cookieParser',
'session',
'refreshSessionCookie',
//'bodyParserInit',
'bodyParser',
'handleBodyParserError',
'compress',
'methodOverride',
'poweredBy',
'$custom',
'requestLogger',
'router',
'www',
'favicon',
'404',
'500'
],
bodyParser: (function _configureBodyParser(){
let skipper = require('skipper');
let middlewareFn = skipper({
limit: 1073741824,
});
return middlewareFn;
})(),
)
},
// cache: 31557600000
};
However, neither attempt solved my issue as the limit still appears to be set 100kb regardless of anything I've done. How do I implement this correctly, so that the body parser accepts files of up to 50kb? I presume either I am not configuring this correctly or something else is overwriting what I've done.
EDIT: I'm using Sails version > 12.0.X
If you are using Sails > v0.12.x:
module.exports.http = {
middleware: {
// ... options
bodyParser: require('skipper')({ limit: 1073741824 })
}
};
For sails < v0.12.x:
module.exports.http = {
middleware: {
order: [
// ... options
// 'bodyParser', <- remove bodyParser
'skipper', // <-- add skipper
],
skipper: require('skipper')({ limit: 1073741824 })
}
};
Here's the link to the documentation.
Just wondering if you have looked at this Sails GitHubIssue
Seems very much related and from what it seems few people have made it work.
Related
Ok, this is a very specific problem I have been struggling with for over a week now. I am developing a SAP UI5 application where UI testing is done via Opa5/QUnit. Serving the application directly via npm does work without problems, however, using Karma (targeting a headless approach) two problems have surfaced which seem to be caused by the used custom Middleware:
res.status() / res.header() do not work (only native node methods like res.setHeader())
Using a body parser (no matter wheter express.json() or deprecated bodyparser.json()), the parser middleware seems to be working forever until the browser request fails after exact 20 or 40 seconds (Chrome only shows the "Stalled" timebar). This happens very often, but not always.
While there is a workaround for the first issue (but still - would be interesting to know why this happens only with Karma) I can't find a solution for the failing requests. I tried changing the browser Karma uses, changing from HTML to script mode, including several plugins and also analyzed packets via Wireshark because browsers show no difference at all between normal and Karma execution.
Through Wireshark I found out that the Karma browser keeps closing Websockets after requests are done while the normal browser doesn't (even when application is served via Karma). Also, in rare cases of working POST JSON requests, content length or processing time do not seem to have an effect.
karma.conf.js:
module.exports = function(config) {
"use strict";
config.set({
frameworks: ['ui5'],
reporters: ["progress"],
browsers: ["Chrome_without_security"],
ui5: {
mode: "html",
testpage: "webapp/test/integration/opaTests.qunit.html",
configPath: "ui5-testing.yaml",
},
customLaunchers: {
Chrome_without_security: {
base: 'Chrome',
flags: ['--disable-web-security', '--no-sandbox']
}
},
singleRun: true,
browserNoActivityTimeout: 400000,
//logLevel: config.LOG_DEBUG,
});
};
ui5-testing.yaml:
specVersion: '2.1'
metadata:
name: grunt-build
type: application
framework:
name: SAPUI5
version: "1.84.0"
libraries:
- name: sap.m
- name: sap.ui.core
- name: sap.ui.layout
- name: sap.ui.support
development: true
- name: sap.ui.table
- name: sap.ui.unified
#- name: sap.ui.model
- name: sap.ushell
development: true
- name: themelib_sap_fiori_3
optional: true
- name: themelib_sap_belize
optional: true
#- name: themelib_sap_bluecrystal
# optional: true
- name: sap.f
- name: sap.tnt
resources:
configuration:
paths:
webapp: /webapp
server:
customMiddleware:
- name: proxy
beforeMiddleware: serveResources
configuration:
testing: true
---
specVersion: '2.1'
kind: extension
type: server-middleware
metadata:
name: proxy
middleware:
path: lib/middleware/proxy.js
proxy.js:
const express = require('express')
module.exports = function ({
resources,
middlewareUtil,
options
}) {
require('dotenv').config();
const axios = require('axios')
var admin = require('firebase-admin');
const app = express();
...
app.use(express.json());
app.use((req, res, next) => { // Most POST Requests with application/json header do not enter this!
...
}
return app;
};
Requesting method (example):
upsert: function (aElements, iTimeout) {
let that = this;
return new Promise((resolve, reject) => {
let sBody = JSON.stringify(aElements);
let xhr = new XMLHttpRequest();
xhr.open('POST', UPSERT_URL, true);
xhr.onload = function (oResponse) {
that.proceedResponse(oResponse, this)
.then(() => resolve())
.catch(iStatus => reject(iStatus));
};
xhr.onerror = function (oError) {
reject(oError);
};
xhr.ontimeout = function (oError) {
console.error(`The request for ${UPSERT_URL} timed out.`);
reject(oError);
};
xhr.timeout = iTimeout;
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(sBody);
});
},
Normal call: ui5 serve -p 8080 -o /test/integration/opaTests.qunit.html --config ui5-testing.yaml
Karma call: karma start
Maybe someone is able to help me here, thank you very much!
I am using glue to spin up the hapi server so I gave the json object with connection and registration details.
I have 10 routes and i need to use authentication strategy for all the 10 routes, So followed the below steps
1) I have registered the xyz custom auth plugin
2) Defined the strategy server.auth.strategy('xyz', 'xyz', { });
3) At every route level I am enabling auth strategy
auth: {
strategies: ['xyz'],
}
How can I give below line to glue configuration object itself.
server.auth.strategy('xyz', 'xyz', { });
Glue.compose(ServerConfig, { relativeTo: baseDir }, (err, server) => {
internals.server = server;
})
One more question here is, in this line server.auth.strategy('xyz', 'xyz', { from json file}); I am reading the JSON data from a config file. When I change the data in this JSON file I dont want to restart the server manually to load the modified data. Is there any plugin or custom code to achieve this?
I figured out a general workaround for when you want to do setup that Glue does not directly support (AFAIK) and you also don't want to keep adding to index.js.
Create a plugins folder where your manifest.js is located.
Create a file plugins/auth.js (in this case). Here you will have a register callback with access to the server object and you can make setup calls that go beyond what Glue does declaratively.
Add a plugin item to manifest.js pointing to your plugin file.
in manifest.js:
register: {
plugins: [
{
plugin: './plugins/auth',
},
]
}
in plugins/auth.js:
module.exports = {
name: 'auth',
async register (server) {
await server.register([
require('#hapi/cookie'),
]);
server.auth.strategy('session', 'cookie', {
cookie: {
name: 'sid-example',
password: '!wsYhFA*C2U6nz=Bu^%A#^F#SF3&kSR6',
isSecure: false
},
redirectTo: '/login',
validateFunc: async (request, session) => {
const account = await users.find(
(user) => (user.id === session.id)
);
if (!account) {
return { valid: false };
}
return { valid: true, credentials: account };
}
});
server.auth.default('session');
},
};
(auth setup code is from the Hapi docs at enter link description here)
This is the way I have found where I can call things like server.auth.strategy() sort-of from manifest.js.
Note: Auth is not a great example for this technique as there is a special folder for auth strategies in lib/auth/strategies.
In my Ember app (based on engines), I do not see hash in the localhost URL
I did try changing locationType in environment.js
locationType: 'hash'
Though the routing & everything is working fine, I am just wondering how do I get the # in the address bar URL.
Below is my complete environment.js
/*jshint node:true*/
'use strict';
module.exports = function(environment, appConfig) {
console.log(environment);
var ENV = {
modulePrefix: 'myapp-ui',
environment: environment,
rootURL: '/myapp/',
locationType: 'auto',
EmberENV: {
FEATURES: {
// Here you can enable experimental features on an ember canary build
// e.g. 'with-controller': true
},
EXTEND_PROTOTYPES: {
// Prevent Ember Data from overriding Date.parse.
Date: false
}
},
APP: {
// Here you can pass flags/options to your application instance
// when it is created
},
TRACKING_ENABLED: true,
LOG_TRACKING_ENABLED: false,
ROUTE_TRANSITION_TRACKING_ENABLED: false,
LOG_ERROR_TRACKING: true,
ANALYTICS_URL:"X",
ANALYTICS_SITE_ID:0,
STUB_MODE : false,
SET_LOCALE : true
};
if (environment && environment !== 'development') {
ENV.rootURL = "";
}
return ENV;
};
Update your config/environment.js's locationType config option to hash and restart your Ember server.
locationType: 'hash', // inside ENV
Quote from Ember guies,
You can change this option in config/environment.js under ENV.locationType.
https://guides.emberjs.com/v2.2.0/configuring-ember/specifying-url-type/
In your 'Router.js' file in the root of your app, you add these lines of code:
Router.reopen({
location: 'hash'
});
More info on hash here: HASHLOCATION ember
Then go to localhost:4200/#/
I'm setting up a basic Sails.js app, and I'm trying to disable the default routing system in sails.js. The documentation here seems to indicate it can be disabled in the /config/blueprints.js file, by setting module.exports.blueprints = { actions: false };
However, when I do sails lift, I'm still able to access my default controller at /foo
Edit: This is using Sails v0.10.5, with no changes other than the two files below.
/** /api/controllers/FooController.js **/
module.exports = {
index: function(req, res) {
return res.send("blah blah blah");
}
};
/** /config/blueprints.js **/
module.exports.blueprints = {
actions: false,
rest: false,
shortcuts: false,
prefix: '',
pluralize: false,
populate: false,
autoWatch: true,
defaultLimit: 30
};
Additionally, the issue continues to occur if I disable blueprints on a per-controller basis:
/** /api/controllers/FooController.js **/
module.exports = {
_config: { actions: false, shortcuts: false, rest: false },
index: function(req, res) {
return res.send("blah blah blah");
}
};
The controller is still accessible at /foo
The problem is a little bit tricky. You are trying to open Controller.index method.
At the same time you are disabled routing for all actions.
But actually Sails.js in 0.10.5 has additional configuration that disables index route from controller.
Its name: index.
So you disabled auto routing for all actions except index..
To disable all auto routes you have to set:
_config: {
actions: false,
shortcuts: false,
rest: false,
index: false
}
Seems that somebody just forgot to add this into docs.
You can do this by using policies under the config folder.
module.exports.policies = {
YourControllerName: {
'find': true,
'*': false
}
}
To disable the default rest routes generated for models you should set rest: false
in file /config/blueprints.js
This solution is for sails V1.x
/***************************************************************************
* *
* Automatically expose RESTful routes for your models? *
* *
***************************************************************************/
rest: false,
Hi Iam trying to set firefox profile name in environment settings of intern config file.I have tried
environments: [
{ browserName: 'firefox',firefox_profile:'default' },
{firefox_profile:'default'}
],
and
environments: [
{ browserName: 'firefox',profile:'default' },
{profile:'default'}
],
as well as
capabilities: {
'selenium-version': '2.42.0',
firefox_profile:'default'
},
as mentioned in Selenium capabilities
But still firefox launches with an anonymous profile.
However if I use watir,
def setup
#browser = Watir::Browser.new :firefox, :profile => 'default'
goto_ecp_console_manage_page
end
browser launches the default profile which is 'kinit-ed'(kerberos)
As the Selenium capabilities page you mention points out, the value of firefox_profile must be a Base64-encoded profile. Specifically, you ZIP up a Firefox profile directory, Base64 encode it, and use that string as the value of firefox_profile. The firefox-profile npm package can make this process easier. You'll end up with something like:
environments: [
{ browserName: 'firefox', firefox_profile: 'UEsDBBQACAAIACynEk...'; },
...
],
I would recommend storing the profile string in a separate module since it's going to be around 250kb.
I used #jason0x43 suggestion to rely on the firefox-profile Node.js module and I've created the following grunt task fireforProfile4selenium. With a simple configuration set into the Gruntfile.js, the plugin writes a file on disk with the Base64 encoded version of a zipped profile!
Here is the grunt configuration:
firefoxProfile4selenium: {
options: {
proxy: {
host: '...',
port: ...
},
bypass: [ 'localhost', '127.0.0.1', '...' ]
},
default: {
files: [{
dest: 'firefoxProfile.b64.txt'
}]
}
}
Here is the plugin:
/*global require, module*/
var fs = require('fs'),
FirefoxProfile = require('firefox-profile'),
taskName = 'firefoxProfile4selenium';
module.exports = function (grunt) {
'use strict';
grunt.registerMultiTask(taskName, 'Prepares a Firefox profile for Selenium', function () {
var done = this.async(),
firefoxProfile = new FirefoxProfile(),
options = this.options(),
host = this.options().proxy.host,
port = this.options().proxy.host,
bypass = this.options().bypass,
dest = this.files[0].dest;
// Set the configuration type for considering the custom settings
firefoxProfile.setPreference('network.proxy.type', 2);
// Set the proxy host
firefoxProfile.setPreference('network.proxy.ftp', host);
firefoxProfile.setPreference('network.proxy.http', host);
firefoxProfile.setPreference('network.proxy.socks', host);
firefoxProfile.setPreference('network.proxy.ssl', host);
// Set the proxy port
firefoxProfile.setPreference('network.proxy.ftp_port', port);
firefoxProfile.setPreference('network.proxy.http_port', port);
firefoxProfile.setPreference('network.proxy.socks_port', port);
firefoxProfile.setPreference('network.proxy.ssl_port', port);
// Set the list of hosts that should bypass the proxy
firefoxProfile.setPreference('network.proxy.no_proxies_on', bypass.join(','));
firefoxProfile.encoded(function (zippedProfile) {
fs.writeFile(dest, zippedProfile, function (error) {
done(error); // FYI, done(null) reports a success, otherwise it's a failure
});
});
});
};