I have developed a web application using React on top of Ethereum blockchain.
One of the pages in my application gets information from user like this:
class AssetNew extends Component {
state = {
name: "",
description: "",
manufacturer: "",
price: "",
errorMessage: ""
};
onSubmit = async event => {
event.preventDefault();
const { name, description, manufacturer, price} = this.state;
this.setState({errorMessage: "" });
try {
const accounts = await web3.eth.getAccounts();
await tracker.methods
.createAsset(name, description, manufacturer, price)
.send({
from: accounts[0],
value: web3.utils.toWei(this.state.price, "ether"),
gas: "1000000"
});
} catch (err) {
this.setState({ errorMessage: err.message });
}
};
render() {
return (
<Form onSubmit={this.onSubmit} error={!!this.state.errorMessage}>
<Form.Field>
<label>Name</label>
<Input
value={this.state.name}
onChange={event => this.setState({ name: event.target.value })}
/>
</Form.Field>
.... // three more from.field for description, manufacturer and price
);
}
}
export default AssetNew;
This page gets name, description, manufacturer, and price and sends it to the smart contract to register a new product. Everything works fine with the browser (I can create a new product with the form).
However, I am not able to create a new product with Jmeter.
I tried to send parameters with POST Method:
After running the test Http requests are successful but nothing happens (I expect Jmeter to create a new product).
Should I expect Jmeter to create a new product by passing parameters?
Do I check the performance correctly?
Smart contract to create a new product:
contract AssetTracker {
uint public id;
uint nonce;
struct Asset {
string name;
string description;
string manufacture;
uint price;
uint id;
address owner;
bool initialized;
}
Asset[] public assets;
function createAsset(string name, string description, string manufacture, uint price) public payable{
id = uint(keccak256(now, msg.sender, nonce)) % 1000;
nonce++;
Asset memory newAsset = Asset(name, description, manufacture, price, id, msg.sender, true);
assets.push(newAsset);
}
If you're able to send the request using the browser, you should be able to use JMeter's HTTP(S) Test Script Recorder in order to capture the relevant HTTP POST Request and generate HTTP Request sampler
Prepare JMeter for recording. The fastest way is using JMeter Templates feature
From JMeter's main menu choose File - Templates - Recording and click "Create"
Expand HTTP(S) Test Script Recorder and click "Start"
Prepare your browser for recording. Configure it to use JMeter as the proxy
localhost or 127.0.0.1 as the proxy host
8888 as the proxy port
make sure that the proxy is set to all protocols and there are no exceptions
If you plan to record HTTPS traffic - import ApacheJMeterTemporaryRootCA.crt certificate into your browser, the certificate is generated in "bin" folder of your JMeter installation when you start the HTTP(S) Test Script Recorder
Execute the request in browser
JMeter should capture the request and store the HTTP Request sampler under Thread Group - Recording Controller.
More information: Apache JMeter HTTP(S) Test Script Recorder
Alternatively you can use JMeter Chrome Extension for creating the test plan, in this case you will not have to worry about proxies and certificates.
Related
I am building an application using the Twitter API and Netlify (aws lambda functions)
This API requires these steps:
When the user goes to my /auth function, a link to the Twitter authentication is created
Once the user clicks that link, he is redirected to Twitter where a pop-up asks to allow my app to connect.
Once the user approves, he is redirected to my /auth function again but this time the authCode is set to a number rather than being undefined. This authCode is used to instantiate the twitter client class and authorize it.
A new instance of the Twitter client is created and authorized. This instance allows to query the tweets
1, 2 and 3 works. However, the authorized instance only lives inside the /auth function. How can I pass it to different functions without losing its instantiation?
How can I pass this instance to different server-less functions?
client = new Client(OAuthClient) this is what I want to pass around.
I tried with a Middleware with little success. It seems the twitter client class gets re-instantiated (so without authorization) for every server-less function
https://playful-salmiakki-67d50e.netlify.app/.netlify/functions/auth
import Client from 'twitter-api-sdk';
let client: Client;
const auth = async (event, context, callback) => {
const authCode = event.queryStringParameters ? event.queryStringParameters.code : undefined;
const authUrl = OAuthClient.generateAuthURL({
state: 'STATE',
code_challenge: 'challenge',
});
console.log('HERE LINK:');
console.log(authUrl);
if (authCode) {
await OAuthClient.requestAccessToken(authCode as string);
client = new Client(OAuthClient); <-- THIS IS WHAT I WANT TO PASS TO DIFFERENT FUNCTIONS
}
return {
statusCode: 200,
body: JSON.stringify({ message: 'Auth, go to the url displayed terminal'}),
myClient: client
};
};
exports.handler = middy().use(myMiddleware()).handler(auth);
I am using Google Reverse Geocoding API from Browser.
The API works fine when using API Key with no restriction.
For example: https://maps.googleapis.com/maps/api/geocode/json?key=API_KEY_WITH_NO_RESTRICTION&latlng=41.8857156,-87.64823779999999 - OK
But as I am calling the API from the browser, I would like to restrict the API Key, preferably request originating from certain domains.
Now, as per the restriction guideline, HTTP Referer restrictions won't work for the Geocoding API (one of the Google Web Service API). It returns error "API keys with referer restrictions cannot be used with this API." in such case!
The other option is to use IP address restriction. But it seems to be more suited if the call was originating from the server. In that case server address could be added in the restriction.
How can I secure (restrict) the API Key if I want to continue to call the Geocoding API from the browser?
I figured out that I have to use Maps Javascript API in order to be able to call the Reverse Geocoding (Address Lookup) from browser (client) with HTTP Referer restrictions in place for the API Key.
In my initial implementation I used fetch(requestUrl) from the browser as it seemed very convenient and ended up with the above problem.
Example (using TypeScript):
Enable Maps Javascript API
Install required packages
npm install #googlemaps/js-api-loader
npm i -D #types/google.maps
reverseGeo.ts
import { Loader } from '#googlemaps/js-api-loader';
const loadScript = async (): Promise<void> => {
const loader = new Loader({
apiKey: API_KEY_WITH_REFERRER_RESTRICTION,
version: 'weekly',
});
await loader.load();
};
export async function reverseGeo(
lat: number, long: number
): Promise<string> {
await loadScript();
const geocoder = new google.maps.Geocoder();
const latlng = {
lat: lat,
lng: long,
};
try {
const { results } = await geocoder.geocode({ location: latlng });
if (results && results[0]) {
return results[0].formatted_address;
}
} catch (e) {
// handle exception
}
throw new TypeError('Zero result or reverse geo Failed'); // or handle other way
}
reverseGeo.spec.ts
import { reverseGeo} from './reverseGeo';
it('should test reverseGeo', async () => {
console.log(reverseGeo(22.5726, 88.3639));
});
I need to send a specific user ID from the bot emulator (https://github.com/microsoft/BotFramework-Emulator). I use this textbox (see on a picture below)
But nothing sent. There is absolutely another guid in activity.From.Id.
Is it possible to sent message from emulator with a specific user ID?
The short answer is, if you are using Direct Line to generate a token from a secret and you specify user Id there (see attached code), then Emulator should favor that value over any value you pass in thru the Emulator settings.
In my personal testing, the User ID setting seems to be overriding any other pre-existing value.
It should be noted, however, that if you specify a User ID value in settings, you will need to close the tabbed conversation and start it anew by re-entering the messaging endpoint and AppId/AppPassword (or reconnecting to your .bot file, if used). Simply pressing "Restart conversation" will not cause Emulator to pickup the User ID setting.
Hope of help!
// Listen for incoming requests.
server.post('/directline/token', (req, res) => {
// userId must start with `dl_` for Direct Line enhanced authentication
const userId = (req.body && req.body.id) ? req.body.id : `dl_${ Date.now() + Math.random().toString(36) }`;
const options = {
method: 'POST',
uri: 'https://directline.botframework.com/v3/directline/tokens/generate',
headers: {
'Authorization': `Bearer ${ process.env.directLineSecret }`
},
json: {
user: {
Id: `${ userId }`
}
}
};
request.post(options, (error, response, body) => {
if (!error && response.statusCode < 300) {
res.send(body);
console.log('Someone requested a token...');
} else {
res.status(500).send('Call to retrieve token from DirectLine failed');
}
});
});
I am using Nightwatch and was hoping to monitor the http requests that are being generated by my nightwatch steps. Is there a way to listen to the requests that are sent and the responses received. I dont need to modify them.
Thanks
Matt
Yes there is a way.
In order to monitor the HTTP requests:
It's basically will monitor when user click on event that send a
request to the server such as: submit button in login page - that send userName & password.
First install npm i nightwatch-xhr
after that you can make a function like that:
module.exports = {
tags: ["test"],
"test": function (browser) {
browser
.windowMaximize()
.url("some url")
.insertValue("namevalue")
.insertValue("passwordValue")
//then write something like that
.waitForXHR(
"",
1000,
function browserTrigger() {
browser.click("submit button")
},
function assertValues(xhr) {
console.log(xhr)
}
);
}
}
It will catch the request data that send to the server.
private async Task Run()
{
//setting up OAuth 2.0 authentication
ClientSecrets secret = new ClientSecrets
{
ClientId = <My ID Here>,
ClientSecret = <My Secret Here>
};
UserCredential credentials = await GoogleWebAuthorizationBroker.AuthorizeAsync(secret, new[] { Scope }, "user", CancellationToken.None);
//create the service
service = new DoubleclicksearchService(new BaseClientService.Initializer()
{
HttpClientInitializer = credentials,
ApplicationName = <My Application Name Here>
});
//make request to download keywords; response variable will hold Id of generated report
Report response = await service.Reports.Request(CreateRequestBody()).ExecuteAsync();
Console.WriteLine("Created Report: ID={0}", response.Id);
}
First time user of the DoubleClick Search API. The above code is my snippet attempting to make a keyword report request. Each run however, the service.Reports.Request line throws an exception. Specifically the error is:
"Google.Apis.Requests.RequestError\r\nForbidden [403]\r\nErrors [\r\n\tMessage[Forbidden] Location[ - ] Reason[forbidden] Domain[global]\r\n]\r\n"
Any ideas what's going on here? If I make the call without the ExecuteAsync() part it works fine, but then I can't get at the Id of the submitted report.
For those interested, it appears ExecuteAsync was the wrong method to use here. The retrieval of the Report object that contains the ID of the report being generated is not created asynchronously, I believe. When I changed the last bit of code to
//make request to download keywords; response variable will hold Id of report to be generated
var request = service.Reports.Request(CreateRequestBody());
response = request.Execute();
Console.WriteLine("Report being generated. Report ID: {0}", response.Id);
it worked as expected.