I have tried both AWS Go SDKs both versions and every time I get an error stating that the Details field is malformed. The Details field accepts a JSON string.
In SDK V2 you basically have a struct for the event
type Event struct {
Details []struct {
Key string `json:"Key"`
Value string `json:"Value"`
} `json:"Details"`
DetailType string `json:"DetailType"`
Source string `json:"Source"`
}
The example then builds up the JSON string with this code
myDetails := "{ "
for _, d := range event.Details {
myDetails = myDetails + "\"" + d.Key + "\": \"" + d.Value + "\","
}
myDetails = myDetails + " }"
And then make the api call
input := &cloudwatchevents.PutEventsInput{
Entries: []types.PutEventsRequestEntry{
{
Detail: &myDetails,
DetailType: &event.DetailType,
Resources: []string{
*lambdaARN,
},
Source: &event.Source,
},
},
}
Basically I get an error saying that the string assigned to the Detail field is malformed. I believe this is because the example code generates a string with a trailing which is not valid . However when you omit the , you get a nil memory reference.
AWS SDK Example
The example for SDK version 1 also generates an error.
Any help would be great
The code on the page you linked is not 100% correct. They actually link the "complete example" at the bottom of the page, which has slightly different code:
https://github.com/awsdocs/aws-doc-sdk-examples/blob/main/gov2/cloudwatch/PutEvent/PutEventv2.go#L108-L117
myDetails := "{ "
for i, d := range event.Details {
if i == (len(event.Details) - 1) {
myDetails = myDetails + "\"" + d.Key + "\": \"" + d.Value + "\""
} else {
myDetails = myDetails + "\"" + d.Key + "\": \"" + d.Value + "\","
}
}
myDetails = myDetails + " }"
But building the JSON like this is not ideal and error-prone, as you already found out.
I'd propose the following:
details := make(map[string]string, len(event.Details))
for _, d := range event.Details {
details[d.Key] = d.Value
}
b, err := json.Marshal(details)
if err != nil {
return
}
fmt.Println(string(b))
Checkout the playground to see it in action:
https://play.golang.com/p/E4ueZLGIKp4
Related
Hello I am using AWS SES SDK V2 to send emails. I have a case where sender name is like Michael čisto. If I pass this name directly to AWS email input struct then it gives me following error:
operation error SESv2: SendEmail, https response error StatusCode: 400, BadRequestException: Missing '"'
Here is my code:
package main
import (
"context"
"github.com/aws/aws-sdk-go-v2/aws"
awsconfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/sesv2"
"github.com/aws/aws-sdk-go-v2/service/sesv2/types"
)
func main() {
name := "Michael čisto"
body := "test email body"
subject := "test email"
CharSet := "UTF-8"
/* Assemble the email */
input := &sesv2.SendEmailInput{
Destination: &types.Destination{
CcAddresses: []string{},
ToAddresses: []string{receiverEmail},
},
Content: &types.EmailContent{
Simple: &types.Message{
Body: &types.Body{
Html: &types.Content{
Charset: aws.String(CharSet),
Data: aws.String(body),
},
},
Subject: &types.Content{
Charset: aws.String(CharSet),
Data: aws.String(subject),
},
},
},
ReplyToAddresses: []string{"\"" + name + "\" <" + senderEmail + ">"},
FromEmailAddress: aws.String("\"" + name + "\" <" + senderEmail + ">"),
}
cfg, err := awsconfig.LoadDefaultConfig(context.TODO(),
awsconfig.WithRegion("us-east-1"),
)
client := sesv2.NewFromConfig(cfg)
emailResp, err = client.SendEmail(context.TODO(), input)
}
Can anyone help me to figure out how to escape these kind of characters in GO ?
Try to format the address using mail.Address.String:
package main
import (
"fmt"
"net/mail"
)
func main() {
a := mail.Address{Name: "Michael čisto", Address: "sender#example.com"}
fmt.Println(a.String())
// Output:
// =?utf-8?q?Michael_=C4=8Disto?= <sender#example.com>
}
In case your domain contains non-ASCII characters:
Please note that Amazon SES does not support the SMTPUTF8 extension. If the domain part of an address (the part after the # sign) contains non-ASCII characters, they must be encoded using Punycode (see types.BulkEmailEntry). mail.Address.String does not do this for you. But you can use idna.ToASCII to convert the domain yourself.
I am using Claudia-api-builder to create and deploy the.
https://github.com/claudiajs/example-projects/tree/master/custom-authorizers
My AWS custom authorizer looks like this :
let jwtDecode = require('jwt-decode');
var generatePolicy = function (authToken, methodArn) {
'use strict';
var tmp = methodArn.split(':'),
apiGatewayArnTmp = tmp[5].split('/'),
awsAccountId = tmp[4],
region = tmp[3],
restApiId = apiGatewayArnTmp[0],
stage = apiGatewayArnTmp[1];
let group = jwtDecode(authToken)["cognito:groups"];
if (group[0] === 'Admin') {
return {
'principalId': authToken.split('-')[0],
'policyDocument': {
'Version': '2012-10-17',
'Statement': [{
'Effect': 'Allow',
'Action': [
'execute-api:Invoke'
],
'Resource': [
'arn:aws:execute-api:' + region + ':' + awsAccountId + ':' + restApiId + '/' + stage + '/GET/citizens',
'arn:aws:execute-api:' + region + ':' + awsAccountId + ':' + restApiId + '/' + stage + '/GET/citizens/{citizenId}/personal-details'
]
}]
}
};
}
exports.auth = function testAuth(event, context, callback) {
'use strict';
console.log('got event', event);
/*
* {
* "type":"TOKEN",
* "authorizationToken":"<Incoming bearer token>",
* "methodArn":"arn:aws:execute-api:<Region id>:<Account id>:<API id>/<Stage>/<Method>/<Resource path>"
* }
*/
if (event && event.authorizationToken && event.methodArn) {
callback(null, generatePolicy(event.authorizationToken, event.methodArn));
} else {
callback('Unauthorized');
}
};
The first API from the resource is working fine, but when I am calling the 2nd API i:e :
'arn:aws:execute-api:' + region + ':' + awsAccountId + ':' + restApiId + '/' + stage + '/GET/citizens/{citizenId}/personal-details'
It is giving me 403 Forbidden with :
{
"Message": "User is not authorized to access this resource"
}
In my case, Authorization Caching is also disabled
Any solution for this issue?
The resource should not be the path of the API Gateway method.
In fact it should be the Arn of the resource. You can get this from the AWS console by performing the following:
Open API Gateway
Select your API Gateway
Click the Resources option
Find your resource (This will be the GET method underneath citizens/{citizenId}/personal-details). Click on it.
There will be an Arn available for you.
When using path based parameters any parameter is replaced by an * so this would become the below.
'arn:aws:execute-api:' + region + ':' + awsAccountId + ':' + restApiId + '/' + stage + '/GET/citizens/*/personal-details'
The solution for me was to make a wildcard resource instead of just passing in event.methodArn into the generateAllow()
a wild card resource looks like this, then you pass it into your generateAllow()
var tmp = event.methodArn.split(':');
var apiGatewayArnTmp = tmp[5].split('/');
var resource = tmp[0] + ':' + tmp[1] + ':' + tmp[2] + ':' + tmp[3] + ':' + tmp[4] + ':' + apiGatewayArnTmp[0] + '/*/*';
generatePolicy("1", 'Allow', resource)
a more in-depth explanation can be found here https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-lambda-authorization-errors/
Anyone have a regex to strip lat/long from a string? such as:
ID: 39.825 -86.88333
To match one value
-?\d+\.\d+
For both values:
(-?\d+\.\d+)\ (-?\d+\.\d+)
And if the string always has this form:
"ID: 39.825 -86.88333".match(/^ID:\ (-?\d+\.\d+)\ (-?\d+\.\d+)$/)
var latlong = 'ID: 39.825 -86.88333';
var point = latlong.match( /-?\d+\.\d+/g );
//result: point = ['39.825', '-86.88333'];
function parseLatLong(str) {
var exp = /ID:\s([-+]?\d+\.\d+)\s+([-+]?\d+\.\d+)/;
return { lat: str.replace(exp, "$1"), long: str.replace(exp, "$2") };
}
function doSomething() {
var res = parseLatLong("ID: 39.825 -86.88333");
alert('Latitude is ' + res.lat + ", Longitude is " + res.long);
}
I am running into an issue with calling the customer record from a passed value on my mapped section of my mapreduce script. It is sending me a debug error of "TypeError: Cannot find function load in object 262059". Where 262059 is the internal ID of the customer passed from the getInputData function.
NetSuite debug image...
Here is the coding of the function that is throwing this error.
function removeLine(r,recordId){
try{
log.audit({title:"removeLine"});
var customerRecord = r.Load({
"type": r.Type.CUSTOMER,
"id": recordId,
"isDynamic": true
});
log.debug({details:"recordId = " + recordId});
var index = rec.getLineCount('item');
log.debug({detaisl:"index = " + index});
for (var cnt = 0; cnt < lineCount; cnt++)
{
log.audit({details:"Round " + cnt})
rec.selectLine({
sublistId: "item",
line: cnt
});
rec.removeLine({
sublistId: "item",
line: cnt
});
}
log.debug(recordId + " Item Pricing has been removed.");
record.save();
}catch(exception){
log.debug("removeLine Error Message:",exception);
}
}
What am I missing or not understanding? I appreciate your guidance.
Brad
I believe the problem lies where you load the record:
var customerRecord = r.Load({
"type": r.Type.CUSTOMER,
"id": recordId,
"isDynamic": true
});
It should be r.load, not r.Load as JavaScript is case-sensitive.
I have unspecified number of html inputs:
<input id="ageInput" />
<input id="nameInput" />
...
and having the following string which is built based on inputs:
s = "{ 'age': '{ageInput}', 'name': '{nameInput}'}"
how could I use regular expression to replace the above string to reflect the current inputs values like this:
s = "{ 'age': " + $('#ageInput').val() + ", 'name': " + $('#nameInput').val() + " }"
Answering your original question, use replace method of string , which accepts function as parameter:
s = s.replace(/\{([^{}]+)\}/g, function (match, g1) {
return $("#" + g1).val()
})
But I would rather use JSON.stringify:
var s = "{ 'age': '{ageInput}', 'name': '{nameInput}'}"
, controlMap = JSON.parse(s)
, data = {}
for(var i in controlMap) {
data[i] = $(controlMap[i]).val()
}
var str = JSON.stringify(data)