Passing policy from fineuploader. The policy is:
{
"expiration": "2015-11-07T20:18:13.326Z",
"conditions": [
{
"acl": "private"
},
{
"bucket": "fine-upload-test"
},
{
"Content-Type": "text/plain"
},
{
"success_action_status": "200"
},
{
"key": "c94d36ee-19eb-49e8-ac30-760b29982391.txt"
},
{
"x-amz-meta-qqfilename": "adstats.txt"
}
]
}
Processing using .net and returning the following json response:
{
"d": "{ \"signature\":\"305A5A46646B522B324B6B6A6D766B314C717072707A49733362633D\", \"policy\":\"eyJleHBpcmF0aW9uIjoiMjAxNS0xMS0wN1QyMDoxODoxMy4zMjZaIiwiY29uZGl0aW9ucyI6W3siYWNsIjoicHJpdmF0ZSJ9LHsiYnVja2V0IjoiZmluZS11cGxvYWQtdGVzdCJ9LHsiQ29udGVudC1UeXBlIjoidGV4dC9wbGFpbiJ9LHsic3VjY2Vzc19hY3Rpb25fc3RhdHVzIjoiMjAwIn0seyJrZXkiOiJjOTRkMzZlZS0xOWViLTQ5ZTgtYWMzMC03NjBiMjk5ODIzOTEudHh0In0seyJ4LWFtei1tZXRhLXFxZmlsZW5hbWUiOiJhZHN0YXRzLnR4dCJ9XX0=\"}"
}
Error is "Response does not include the base 64 encoded policy!"
I have checked the base64 encoded "policy" and it decodes to the exact policy being passed in.
Please, what am I missing.
You are not returning a valid response. Fine Uploader S3 expects you to return a flat JSON response with two properties: signature and policy. Instead, you are returning a JSON response with a "d" property that itself contains signature and policy properties. You can see this clearly in the response pasted into your question.
Related
I have a test helper function createUser that makes an HTTP request to the backend API to create a user. The backend API calls a method on Auth0 client to create a user. The responses I have are set for Auth0 client URL path /api/v2/users.
I am testing a service that has two types of users - an owner of the account and the invitee user. I am calling a helper twice before all the tests:
const owner = await createUser('owner#email.com');
const invitee = await createUser('invitee#email.com');
And I expect owner to have owner#email.com as an email and an invitee#email.com email for invitee .
In order to return two different responses I used Wiremock scenarios. And currently I have the responses like this:
User #1
{
"scenarioName": "user-scenario",
"requiredScenarioState": "Started",
"newScenarioState": "owner-user",
"request": {
"method": "POST",
"urlPattern": "/api/v2/users"
},
"response": {
"status": 201,
"headers": {
"Content-Type": "application/json"
},
"jsonBody": {
"email": "owner#email.com"
}
}
}
User #2
{
"scenarioName": "user-scenario",
"requiredScenarioState": "owner-user",
"request": {
"method": "POST",
"urlPattern": "/api/v2/users"
},
"response": {
"status": 201,
"headers": {
"Content-Type": "application/json"
},
"jsonBody": {
"email": "invitee#email.com"
}
}
}
When I run the tests Wiremock returns the second response for both createUser calls. The second response was created after the first and Wiremock prioritizes the most recently created response. I decided to set the priority: 1 on the first response to force Wiremock to return it and therefore change the scenario state. That worked only on the first test run but not for the subsequent ones.
Sometimes if I delete the Wiremock Docker image and start the container from scratch it returns the responses as expected but then continues returning the second response for both calls.
What am I doing wrong and if it's not how I set up the scenarios what could be the possible reasons for such inconsistency?
Multiple ways to skin this cat - third (response templating) is probably best.
Understanding Scenarios
The first request moves the scenario into state owner-user, and after that all requests will return user #2 for the lifetime of the WireMock instance - in your case, the docker container - unless it is reset.
You can reset it as so: PUT /__admin/scenarios/user-scenario/Started.
The state of a scenario is held in memory, so restarting the container should also reset the state to Started.
See WireMock | Stateful Behaviour | Resetting a single scenario
Using better matching to avoid scenarios
You may not need to use scenarios at all. You can use the request body of the POST to decide which stub to call, based on the email address you are sending.
Assuming your request payload looks like this:
{
"email": "owner#email.com"
}
You can match on the request body as so:
User #1
{
"request": {
"method": "POST",
"urlPattern": "/api/v2/users",
"bodyPatterns": [
{
"matchesJsonPath": {
"expression": "$.email",
"equalTo": "owner#email.com",
}
}
]
},
"response": {
"status": 201,
"headers": {
"Content-Type": "application/json"
},
"jsonBody": {
"email": "owner#email.com"
}
}
}
User #2
{
"request": {
"method": "POST",
"urlPattern": "/api/v2/users",
"bodyPatterns": [
{
"matchesJsonPath": {
"expression": "$.email",
"equalTo": "invitee#email.com",
}
}
]
},
"response": {
"status": 201,
"headers": {
"Content-Type": "application/json"
},
"jsonBody": {
"email": "invitee#email.com"
}
}
}
See WireMock | Request Matching | JSON Path for details.
Using response templating to reduce number of stubs
You can use values passed to WireMock in the request in the response using response templating as so:
{
"request": {
"method": "POST",
"urlPattern": "/api/v2/users"
},
"response": {
"status": 201,
"headers": {
"Content-Type": "application/json"
},
"transformers": ["response-template"],
"jsonBody": {
"email": "{{jsonPath request.body '$.email'}}"
}
}
}
See WireMock | Response Templating | JSONPath helper for details.
There are also a variety of helpers for generating random data in various formats should you need each request to return some different value (e.g. a UUID) - see WireMock | Response Templating | Random value helper for details.
In an AWS lambda written in Node.js, I want to extract the following part of a URL when I do a GET call through the API gateway:
/devices/{id} --> {id} will be replaced by a value, and that is the value I want!
I know that to get QueryStringParameters you just use
event.queryStringParameters.[parameter name]
But how will I do this for path parameters, like for {id} above.
Also is there a good place where I can comprehensively learn about writing lambdas for APIs in Node.js?
Short answer:
const { id } = event.pathParameters;
I recently released a short training video that demonstrates in detail how to create API Gateway REST APIs and integrate them with AWS Lambda (NodeJS). Please check it out here:
Serverless Architecture: AWS API Gateway & Lambda
I'm assuming you are using lambda proxy here i'm pasting the event object sample for lambda proxy.
{
"message": "Good day, John of Seattle. Happy Friday!",
"input": {
"resource": "/{proxy+}",
"path": "/Seattle",
"httpMethod": "POST",
"headers": {
"day": "Friday"
},
"queryStringParameters": {
"time": "morning"
},
"pathParameters": {
"proxy": "Seattle"
},
"stageVariables": null,
"requestContext": {
"path": "/{proxy+}",
"accountId": "123456789012",
"resourceId": "nl9h80",
"stage": "test-invoke-stage",
"requestId": "test-invoke-request",
"identity": {
"cognitoIdentityPoolId": null,
"accountId": "123456789012",
"cognitoIdentityId": null,
"caller": "AIDXXX...XXVJZG",
"apiKey": "test-invoke-api-key",
"sourceIp": "test-invoke-source-ip",
"accessKey": "ASIXXX...XXDQ5A",
"cognitoAuthenticationType": null,
"cognitoAuthenticationProvider": null,
"userArn": "arn:aws:iam::123456789012:user/kdeding",
"userAgent": "Apache-HttpClient/4.5.x (Java/1.8.0_131)",
"user": "AIDXXX...XXVJZG"
},
"resourcePath": "/{proxy+}",
"httpMethod": "POST",
"apiId": "r275xc9bmd"
},
"body": "{ \"callerName\": \"John\" }",
"isBase64Encoded": false
}
}
the path can be extracted from "path" key in event object, it can be accessed from event.path and after that you can use string manipulation function to further manipulate it.
I hope it helps !
Use brackets in the resource path, as image above. Then in node.js user the code below:
exports.handler = async function(event) {
let serviceId = event.pathParameters.id;
}
The solution is very similar to what you mentioned in the first place. Just use event.pathParameters instead of event.queryStringParameters.
Here I'm using /api/test/{id} as my resource path and using Lambda Proxy integration. I'm getting the following event when I hit https://www.dummyapi.com/dev/api/test/id-123456
This has taken me awhile to figure out on my own so hoping this helps someone. After defining the Path Parameter on the Resource in API Gateway.
AWS Guide including PathParameter Steps: https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-create-api-step-by-step.html
If using CloudFormation: https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-proxy-path-parameter-error/
My path /user/{userId}
My Path Parameter: userId
Then in my lambda function you can access the path via event.path which will have your parameters in object form: path: { userId: 9812 } }. Lots of documentation has it labeled as pathParameters but for whatever reason with this setup it doesn't come through that way.
export const getUser = async (event) => {
console.log(event);
const { userId } = event.path;
}
serverless.yaml
events:
- http:
path: user/{userId}
method: get
request:
parameters:
paths:
userId: true
integration: lambda
I recently switched from the V1 to V2 for dialogflow and I'm updating my webhook.
I use mediaObjects with large Images in my agent as a personal taste.
Unfortunately I can't seem to make it work for the V2.
My current code for the media object is this:
conv.ask(new MediaObject({
name: 'Name',
largeImage: new Image({
url: 'https://[...].jpg',
alt: 'alternative'
}),
url: 'https://[...].mp3',
description: 'description'
}));
As you can see, I used the largeImage field, as I found it in the JSON section of Google's example . As the documentation is inexistant, I'm checking the node.js library for information and I verified that the largeImage field extends the Image interface so it should be correct.
It works when I switch largeImage for Icon but I don't like it.
My JSON response is like this:
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "text"
}
},
{
"mediaResponse": {
"mediaType": "AUDIO",
"mediaObjects": [
{
"contentUrl": "https://[...].mp3",
"description": "description",
"name": "name"
}
]
}
}
],
"suggestions": [
{
"title": "Not yet implemented"
}
]
},
"userStorage": "{\"data\":{}}"
}
}
For some reason the largeImage field doesn't appear in my JSON but there isn't any error appearing anywhere.
Some of the APIs in JSON do not match the Node.js parameters. For example, largeImage in JSON is actually image in the MediaObjectOptions definition.
I'm trying to send a transactional email via node using sendGrid. Below is an example of my code.
const subject = 'Email subject';
const templateId = 'templateId';
const sg = require('sendgrid')(secret);
const request = sg.emptyRequest({
method: 'POST',
path: '/v3/mail/send',
body: {
"personalizations": [
{
"bcc": userEmails,
"substitutions": {
"-userName-": userDetails.name,
"-productPrice-": productDetails.price,
"-productUrl-": productDetails.url,
"-productPercentageDrop-": productDetails.percentageDrop,
"-productName-": productDetails.name,
"-productOriginalPrice-": productDetails.origPrice,
"-productDroppedPrice-": productDetails.dropPrice,
"-productImageUrl-": productDetails.imageUrl
},
"subject": subject.substring(0, 75)
}
],
"from": {
"email": "myemail",
"name": "myname"
},
"content": [
{
"type": "text/html"
}
],
"template_id": templateId
}
});
sg.API(request, function (error, response) {
if (error) {
console.log('Error response received');
}
console.log(response.body.errors);
});
But every time I run the code I get the following error message.
400
message: 'Bad Request', field: null, help: null
Which isn't really that helpful when trying to find out why its erroring.
Body JSON being sent:
{
"host":"",
"method":"POST",
"path":"/v3/mail/send",
"headers":{
},
"body":{
"personalizations":[
{
"bcc":[
{
"email":"name1#hotmail.com",
"name":"name1"
},
{
"email":"name2#hotmail.com",
"name":"name2"
}
],
"substitutions":{
"-productPrice-":189.5,
"-productUrl-":"http://www.tesco.com/direct/humax-fvp-4000t500-m-smart-freeview-play-hd-digital-tv-recorder-with-wi-fi-500gb/483-1785.prd",
"-productName-":"Tesco direct: Humax FVP-4000T/500 (M) Smart Freeview Play HD Digital TV Recorder with Wi-Fi - 500GB"
},
"subject":"Product Tesco direct: Humax FVP-4000T/500 (M) Smart Freeview Play HD Digita"
}
],
"from":{
"email":"email#pricetracker.io",
"name":"Pricetracker"
},
"content":[
{
"type":"text/html"
}
],
"template_id":"XXXXXX"
},
"queryParams":{
},
"test":false,
"port":""
}
don't know if this could still be helpful for you, but I've had some similar issues when using substitutions with Sendgrid. I'm using the sendgrid-php library, but internally it sends the same format. What I found was that all substitution values should be converted to string. For instance your value for productPrice should be like this:
"-productPrice-": "189.5",
With quotes. In my case I had integers, and when I converted them to strings, all worked correctly.
If you are not passing string value to the template file then SendGrid will give you
{"errors":[{"message":"Bad Request","field":null,"help":null}]}
Convert your all non-string value to string before sending to the template file.
I got same issue, then I fix using this below syntax, change only you message format.
"value": "'.html_entity_decode((str_replace('"',"'",$message))).'"
Can I resolve the issue in JIRA?
I made some trials with REST API as;
var url = "https://hibernate.atlassian.net/rest/api/2/issue/WEBSITE-1/transitions";
var message = [{
"update": {
"comment": [
{
"add": {
"body": "some text for body"
}
}
]
},
"fields": {
"assignee": {
"name": "name1"
},
"resolution": {
"name": "Fix"
}
},
"transition": {
"id": "1"
}
}];
request({
url: url,
method: "POST",
json: true,
body: message,
}, function (error){});
Url(https://hibernate.atlassian.net/rest/api/2/issue/WEBSITE-1/transitions) gives me;
{"expand":"transitions","transitions":[]}
How can I resolve an issue in JIRA? Am I doing wrong?
You've got the right approach, but you need to authenticate your requests with a user that has permission to execute the transition.
Because you execute your requests anonymously, JIRA gives you a response that does not contain any transitions you can execute and will not allow you to perform a transition.
Take a look at the documentation for the request module or another example.
To get the full list of transitions, append the string ?expand=transitions.fields to your existing url. So in this case it would look like
var url = "https://hibernate.atlassian.net/rest/api/2/issue/WEBSITE-1/transitions?expand=transitions.fields";