After successfully extracting username and password from a csv as shown in the documentation, I noticed that my username was in the following format: "\ntomer#mail.com". How can I erase the "\n" char in artillery?
P.S.
The way to check your HTTP request is (I was unable to find documentation for this):
In cmd do the following command:
set DEBUG=http,http:capture,http:response
Afterwards, every regular artillery request will give you a http debug mode as following:
http request: {
"url": "https://host.com/api/user/login",
"method": "POST",
"headers": {
"user-agent": "Artillery (https://artillery.io)"
},
"json": {
"email": "\ntomer#mail.com",
"password":"9526e7bb980ba35a1788d46d4a2aaaaa3d941d2efc8a4fcb1402d1"
}
}
}
I solved the problem by using JS as follows (solution is based on this)
In the config section of the yml I set that the JS file to be called would be login.js by adding the following line:
processor: "./js/login.js"
When sending my login request I called the "setJSONBody" function as following:
- post:
url: "https://dev-api.host.com/api/user/login"
beforeRequest: "setJSONBody"
json:
email: "{{ user }}"
password: "{{ password }}"
Here is my login.js file:
//
// my-functions.js
//
module.exports = {
setJSONBody: setJSONBody
}
function setJSONBody(requestParams, context, ee, next) {
context.vars.user = context.vars.user.replace('\n',''); //erases from user name any \n char
return next(); // MUST be called for the scenario to continue
}
Related
I'm trying to get a oauth token from the paypal sandbox using axios. The request looks like this:
const response = await axios.post(
'https://api-m.sandbox.paypal.com/v1/oauth2/token',
new URLSearchParams({
'grant_type': 'client_credentials'
}),
{
auth: {
username: process.env.PP_CLIENT,
password: process.env.PP_SECRET
},
headers: {
'Accept': 'application/x-www-form-urlencoded',
'Accept-Language': 'en_US'
}
}
);
console.log(`response: ${JSON.stringify(response.data)}`);
As far as I can tell this code used to work, because I used it before. However now I'm getting the error:
"Converting circular structure to JSON
--> starting at object with constructor 'ClientRequest'
| property 'socket' -> object with constructor 'TLSSocket'
--- property '_httpMessage' closes the circle"
I have confirmed that my credentials are correct by testing it with curl, which works and by copying it directly into the code. I've also tries fetch (which always yields an empty response)
I am trying to implement an SQL querying interface for an AWS RDS MySQL database in a public web page. Ideally, a user will type a SQL query into a search field, press a "Query" button, and an API Gateway request will trigger a Lambda function to pull, return and print to the web page the relevant data from the database.
So far, I have the following Lambda function (which I am able to successfully test):
const AWS = require('aws-sdk')
const RDS = new AWS.RDSDataService()
exports.handler = async (event, context) => {
console.log(JSON.stringify(event, null, 2)) // Log the entire event passed in
// Get the sqlStatement string value
// TODO: Implement a more secure way (e.g. "escaping") the string to avoid SQL injection
var sqlStatement = event.sqlStatement;
// The Lambda environment variables for the Aurora Cluster Arn, Database Name, and the AWS Secrets Arn hosting the master credentials of the serverless db
var DBSecretsStoreArn = process.env.DBSecretsStoreArn;
var DBAuroraClusterArn = process.env.DBAuroraClusterArn;
var DatabaseName = process.env.DatabaseName;
const params = {
awsSecretStoreArn: DBSecretsStoreArn,
dbClusterOrInstanceArn: DBAuroraClusterArn,
sqlStatements: sqlStatement,
database: DatabaseName
}
try {
let dbResponse = await RDS.executeSql(params).promise()
console.log(JSON.stringify(dbResponse, null, 2))
var json_response = JSON.stringify(dbResponse)
return json_response
} catch (error) {
console.log(error)
return error
}
}
This function, when tested with the following test format, returns a JSON blob I think.
Test event format:
{
"sqlStatement": "SELECT * FROM Table WHERE Name='JOHN DOE'"
}
Test event result:
..., {\"stringValue\":\"JOHN DOE\"},{\"stringValue\":\"2019-11-15\"},{\"stringValue\":\"AL\"},{\"stringValue\":\"1\"},{\"stringValue\":\"130\"},{\"stringValue\":\"Washington Co. Jail\"},{\"stringValue\":\"2019-10-31\"}, ...
I have the following API trigger details configured:
API endpoint: https://****************.amazonaws.com/prod/query
API Type: rest
Authorization: NONE
Method: POST
Resource path: /query
Stage: prod
I also have the following Lambda role configuration policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"rds:*",
"rds-data:*"
],
"Resource": "*"
}
]
}
The API, meanwhile, has the following methods/configurations:
Aside from any potential problems in this setup (i.e. the link between the Lambda and the API trigger and the formats of data passed/queried/returned), I need to figure out how to actually call this whole process from the click of a Query button. So, for example, the user would be on the page, type SELECT * FROM Table WHERE Name="JOHN DOE" into an HTML element, click an HTML button "Query", and the process would implement; then, the query result would populate in whatever format (to be simple, a messy string for now, but ideally eventually in a bootstrap DataTable) inside another HTML element.
I currently have a config.js file that contains:
window._config = {
api: {
invokeUrl: 'https://******************.amazonaws.com/prod',
}
};
I also have a query.js file that contains a function (likely incorrect) attempt based on piecemeal tutorials online:
(function DisplayQuery($) {
var query = document.getElementById("sql-placeholder").value;
function passQuery(query) {
$.ajax({
method: 'POST',
url: _config.api.invokeUrl + '/query',
data: JSON.stringify({
sqlStatement: query
}),
contentType: 'application/json',
success: document.getElementById("text-box").innerHTML = result.value,
error: function ajaxError() {
console.error('Error requesting ride');
}
})
}
}(jQuery));
In my index.html file I have these search field and button elements:
<div class="active-cyan-4 mb-4">
<input id="sql-placeholder" class="form-control" type="text" placeholder="Write SQL here..." aria-label="Search">
</div>
<div class="col-md-1">
<button type="button" class="btn btn-primary" onclick="DisplayQuery()">Query</button>
</div>
Finally, this would be the test element where my string-format SQL query results would appear once they'd been returned by RDS --> Lambda --> API Gateway:
<div class="container-fluid">
<p class= "test-box-class" id="test-box"><i>This is a test box for database query connection</i></p>
</div>
This is a lot perhaps, but I'm wondering if anyone has any insight into how to make this process run, at least well enough so that hitting the Query button returns something to the web page.
After following #antonku's answer, The reason for the "Missing Authentication Token" error was, you are trying to access a "POST" http method in the browser, The browser requests URL using the "GET" http method.
You may also get the same error message when the URL is incorrect.
Add some console.log statements to see the api response in the front end
var DisplayQuery;
(function($) {
DisplayQuery = function() {
$.ajax({
method: 'POST',
url: _config.api.invokeUrl + '/query',
data: $('#sql-placeholder').val(),
contentType: 'application/json',
success: function(response) {
console.log('response: ', response);
$('#test-box').text(JSON.stringify(response))
},
error: function ajaxError(error) {
console.error('Error requesting ride');
}
})
}
}(jQuery));
There are a few issues with the code that makes the ajax request.
On button click DisplayQuery is called, however this name is used for the function that is immediately invoked on the initial page load. Instead on the button click you need to invoke the function that sends the ajax request.
The is also no need to JSON.stringify the input value since it's already a string.
Also, for the success key, it's required to provide a function that accepts the response.
Changing query.js in the following way should resolve these concerns:
var DisplayQuery;
(function($) {
DisplayQuery = function() {
$.ajax({
method: 'POST',
url: _config.api.invokeUrl + '/query',
data: $('#sql-placeholder').val(),
contentType: 'application/json',
success: function(response) {
$('#test-box').text(JSON.stringify(response))
},
error: function ajaxError() {
console.error('Error requesting ride');
}
})
}
}(jQuery));
I want to integrate Quasar with FeathersJS using Feathers-Vuex
Feathers-Vuex uses a pattern to:
promise to authenticate from localStorage/cookies
.then( /*start the new Vue() app */ )
I created my app with Quasar CLI 1.0.beta16-ish and looked through /src and couldn't find the main entry point for Quasar. I feel like I'm missing something.
What includes src/store/index.js?
quasar.conf.js includes this comment - where is the main.js
// app boot file (/src/boot)
// --> boot files are part of "main.js"
boot: ["axios"],
Feathers-Vuex includes a Nuxt integration guide that may solve the same problem. These packages are all new to me, and I'm excited to learn them!
Thank you!
The part of main.js is included in quasar app.js that you can find in .quasar folder. The src/store/index.js contains the Vuex Store definition. A "store" is basically a container that holds your application state.
For more detail visit - https://quasar-framework.org/guide/app-vuex-store.html https://quasar-framework.org/guide/app-plugins.html
I ended up with two things:
Adding Feathers-Vuex to my backend.
Adding this "boot file" in my Quasar project
The comments are a bread-crumb trail if I ever have to figure it out again :-)
/*
Context:
For 3rd-party API's, we us /src/boot/axios.js
For our own API's, we use FeathersClient (socket.io & REST)
https://docs.feathersjs.com/guides/basics/clients.html
https://docs.feathersjs.com/api/authentication/client.html#appconfigureauthoptions
Our FeathersClient is in `/src/lib/feathersClient.js`
and imported into `/src/store/index.js`
which is imported by Quasar's build system. /src/quasar.conf.js setting(?)
Feathers-vuex integrates Vuex with FeathersClient:
https://feathers-vuex.feathers-plus.com/auth-module.html
Feathers-Vuex proxies it's authentication/logout actions to FeathersClient
https://github.com/feathers-plus/feathers-vuex/blob/master/src/auth-module/actions.js
The parameters for these actions are here:
https://docs.feathersjs.com/api/authentication/client.html#appauthenticateoptions
In addition to this module, you can use FeathersVuex state in UI from here:
https://feathers-vuex.feathers-plus.com/auth-module.html
This module:
Create a Feathers Auth integration for Vue as a Quasar Boot Module.
// Use case: test if user is authenticated
if (Vue.$auth.currentUser()) { ... }
// Use case: get current user's email
name = Vue.$auth.currentUser("email") || "anonymous"
// Use case: Login
Vue.$auth.login({
strategy: 'local',
email: 'my#email.com',
password: 'my-password'
});
// Use case: Logout
// logs out and sends message
let p = Vue.$auth.logout();
// After logout, go home
p.then(() => {
// User data still in browser
router.push({ name: "home"});
// To clear user data, do a hard refresh/redirect - https://feathers-vuex.feathers-plus.com/common-patterns.html#clearing-data-upon-user-logout
location && location.reload(true)
});
*/
export default ({ app, router, store, Vue }) => {
// Create the API demonstrated above
const auth = {
currentUser(prop) {
let u = store.state.auth.user || false;
if (u && prop) return u[prop];
return u;
},
login(authData, quiet) {
return store
.dispatch("auth/authenticate", authData)
.then(() => {
Vue.prototype.$q.notify({
message: "Welcome back!",
type: "info"
});
})
.catch(err => {
if (!quiet) {
console.log(err);
Vue.prototype.$q.notify({
message: "There was a problem logging you in.",
type: "error"
});
}
});
},
logout(quiet) {
return store.dispatch("auth/logout").then(() => {
if (!quiet)
Vue.prototype.$q.notify({
message: "You've been logged out.",
type: "info"
});
});
},
register(authData) {}
};
// Auth from JWT stored in browser before loading the app. true => suppress token not found error
auth.login("jwt", true);
// Add API to Vue
Vue.prototype.$auth = auth;
// If you would like to play with it in the console, uncomment this line:
// console.log(auth);
// Then, in the console:
/*
temp1.login({
strategy: "local",
email: "feathers#example.com",
password: "secret"
})
*/
// If you haven't created this user, see here:
// https://docs.feathersjs.com/guides/chat/authentication.html
// For this REST api endpoint
/*
curl 'http://localhost:3001/users/' -H 'Content-Type: application/json' --data-binary '{ "email": "feathers#example.com", "password": "secret" }'
*/
};
I use MongoDB as the back-end database for my node/Express application. To summarize the problem I am facing, I don't know how to set up the body-parser configuration in my Express app, because the server side application is not receiving the full JSON posted by the client application (also a node.js app). For the most part, the client is sending JSON in the request body to RESTful endpoints. The exception being a single case where a file needs to be uploaded and since that is a multipart body, I am using request and form-data to build that type of request and using multer on the server side to process the multipart request, since body-parser does not process such requests.
On the server-side (Express), I have the following configuration of the Express app:
let app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
On the node client, I am using the following code to build up a JSON-style JavaScript object and post it to a RESTful endpoint:
I am having difficulty composing the request on the client side, with node-request:
// class is a JavaScript/JSON object within scope of this code
let req = request.post({
//headers: { 'Content-Type': 'application/json' },
url: 'http://localhost:3000/classes',
//form: class
form: JSON.stringify(class)
}, function (err, resp, body) {
if (err) {
throw err;
}
});
Note that I attempted multiple versions of the above code by explicitly specifying the content type as application/JSON, as well as using JSON.stringify to convert the JavaScript object into a JSON string. The MongoDB collection (class) stores the following type of document, which contains foreign keys to two other collections (subject and student):
{
"_id" : ObjectId("57758f15f68da08c254ebee1"),
"name" : "Grade 5 - Section A",
"scores" : [{
"studentId" : ObjectId("5776bd36ffc8227405d364d2"),
"performance": [{
"subjectId" : ObjectId("577694ecbf6f3a781759c54a"),
"score" : 86,
"maximum" : 100,
"grade" : "B+"
}]
}]
}
In the server logs, I see the following error:
Tue, 05 Jul 2016 04:34:46 GMT classReportApp:routes:classes class received from client: { _id: 577b38e65967097c25876764, scores: [] }
RangeError: Invalid status code: 0
at ServerResponse.writeHead (_http_server.js:192:11)
at ServerResponse.writeHead (C:\Development\classReportApp\node_modules\morgan\node_modules\on-headers\index.js:55:19)
at ServerResponse._implicitHeader (_http_server.js:157:8)
at ServerResponse.OutgoingMessage.end (_http_outgoing.js:566:10)
at ServerResponse.send (C:\Development\classReportApp\node_modules\express\lib\response.js:205:10)
at ServerResponse.json (C:\Development\classReportApp\node_modules\express\lib\response.js:250:15)
at C:\Development\classReportApp\server-process\app.js:80:26
at Layer.handle_error (C:\Development\classReportApp\node_modules\express\lib\router\layer.js:71:5)
at trim_prefix (C:\Development\classReportApp\node_modules\express\lib\router\index.js:310:13)
at C:\Development\classReportApp\node_modules\express\lib\router\index.js:280:7
at Function.process_params (C:\Development\classReportApp\node_modules\express\lib\router\index.js:330:12)
which is strange because scores array of sub-documents is empty (scores: []), whereas on the client side, I am sending a non-empty array with some students' performances elements in it.
Have I violated the right way to post JSON to Express apps? How do I fix this?
Edited: 7/5/2016
I changed the body parser middle-ware configuration to use extended: true instead.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
The node.js is still using the node-request module to compose and send the POST request, using the following code:
let req = request({
url: 'http://localhost:3000/classes',
method: 'POST',
json: class
}, function (err, resp, body) {
if (err) {
throw err;
}
else {
// process response
}
});
This works now, but what confuses me is that since the content type is application/json, how does the bodyParser.urlencoded({ extended: true }) (or false) matter?
Issue is with form: JSON.stringify(class) in your first request. form takes url encoded form input, stringified json won't work. check content-type header (application/x-www-form-urlencoded)
json: class in your 2nd snippet works as this handles json data and sets correct content type header correctly.
Try .toJSON() method over class before sending.
I am trying to register a user in my Hybrid Worklight application. For this I am using an external REST API. The API says:
Request Method: POST
Request URL: https://${domainservice}/service/plan/${planName}/user?key=${key}&tenantId=${tenantId}
Request Headers: Content-Type:application/json
Request Payload:
{
"uid": "patricia",
"firstName": "Patricia",
"lastName": "Mayo",
"pic": "BASE64_ENCODED_IMAGE"
}
Field description:
uid (required): user's uid
firstName (optional): user's first name
lastName (optional): user's last name
pic (optional): user's picture encoded as base64 string
So I created a HTTP Worklight adapter:
function RegisterUser(userid) {
var input = {
method : 'post',
path : '/service/plan/App/user',
returnedContentType : 'plain',
headers: {'Content-Type' : 'application/json'},
parameters: {
'key':'e634bc60-0c6eba577258',
'tenantId': 'd93b921d-a56c-a645924fd548'
},
body : {
'contentType' : 'application/json',
'content' : JSON.stringify({
"uid" : userid})
}
};
return WL.Server.invokeHttp(input);
}
And I get this error:
{ "errors": [
],
"info": [
],
"isSuccessful": true,
"responseHeaders": {
"$wsep": "",
"Connection": "Keep-Alive",
"Content-Language": "en-US",
"Content-Type": "text\/html;charset=ISO-8859-1",
"Date": "Wed, 30 Jul 2014 14:47:27 GMT",
"Transfer-Encoding": "chunked",
"X-Backside-Transport": "FAIL FAIL",
"X-Client-IP": "199.127.32.67",
"X-Global-Transaction-ID": "48515650",
"X-Powered-By": "Servlet\/3.0"
},
"responseTime": 357,
"statusCode": 500,
"statusReason": "Internal Server Error",
I think is very weird that I set up
headers: {'Content-Type' : 'application/json'}
but in the response it looks like
"Content-Type": "text/html;charset=ISO-8859-1"
Also I want to point out some things I have already tried:
returnedContentType : 'plain' --> It is set to plain because if I set it to json I would get a JSON parse error
body content I also tried
var payload = "{\'uid\': \'"+userid+"\'}";
payload = payload.toString();
and then 'content' : payload
Using the RESTClient of the browser everything works fine
I tried using http port 80, http port 2080, and also https 443
I also tried writting the Host in the headers
I would not be too concerned about the format of the payload in the case where the server has hit an error condition - ideally servers would give us nicely formed error response but that's not always possible. Typically, if the expected response type in case of success is JSON then that's what I specify, and I just have to have enough error handling for cases when JSON parsing fails.
As to why you're getting the 500 error ... best I can suggest is to use a network monitor of some sort to discern the difference between the request issued via Worklight and the request as issued by the Browser's REST client.
You can set this up in Eclipse, Preferences->Run->TCP/IP Monitor ...
You may want to add a Host header. I've seen numerous times where it solved similar issues. E.g. if you're trying to connect to http://www.server.com/a/b/c/d add below header to your headers property
headers: {
Host: 'www.server.com'
}
I finally found the error. There is a defect in Worklight, the query parameters are removed and put into request body so the REST SERVICE does not receive key & tenantId. This is the final working code solution. Thank you anyways for your quick answers :)
function RegisterUser(userid) {
var payload = '{"uid": \"'+userid+'\"}';
var input = {
method : 'post',
path : '/service/plan/App/user?key=e630-db87-4803-bc45-57725c&tenantId=d9348af-a56c-a645924fd54e',
returnedContentType : 'application/json',
headers: {'Content-Type' : 'application/json'},
body : {
'contentType' : 'application/json',
'content' : payload.toString()
}
};
return WL.Server.invokeHttp(input);
}