Listen to Pubsub Messages and output to a list - google-cloud-pubsub

I'm listening to a subscription and want to output messages to an array messages and finally post it to an endpoint. But after running this on cloud function, I got console log of all the messages but the body of the request is an empty list.
const messages = [];
const subscription = pubsubClient.subscription(subscriptionNameOrId);
let messageCount = 0;
const messageHandler = message => {
console.log(`New message ${message.id}:`)
messages.push(message.data)
console.log(`\tData: ${message.data}`)
console.log(`\tAttrs: ${JSON.stringify(message.attributes)}`)
messageCount += 1
message.ack()
};
subscription.on('message', messageHandler);
requests.post({
uri: output_endpoint,
headers: {'Content-Type': 'application/json'},
body: {'message': messages},
json: true
});

Related

Passing data as an object from React.js(Client) to Rails_API(local server)

i'm trying to send an object to my server controller as a post action as the following,
It throws an error that the params are nil, using binding.pry i also verified that the params that are passed are :nil,
I pretty sure the issue is in my syntax, but i tried several ways and still same error.
Can somebody help ?
function Metrics() {
const [purchase, setPurchase] = useState({});
const [income, setIncome] = useState({});
const [expenses, setExpenses] = useState({});
const [loan, setLoan] = useState({});
const [equity, setEquity] = useState({});
const [active, setActive] = useState(false);
const [metrics, setMetrics] = useState({
purchaseComp: false,
incomeComp: false,
equityComp: false,
loanComp: false,
expensesComp: false
})
const runMetrics = () => {
let reportObj = {
purchase_price: purchase,
monthly_rent: income.rent,
annual_rent_appreciation: income.appreciation,
annual_property_taxes: expenses.propertyTaxes,
annual_property_repairs: expenses.propertyRepairs,
annual_vacancy_rate: expenses.propertyVacancyRate,
loan_years: loan.years,
loan_rate: loan.rate,
exit_year: equity.exitPoint,
property_appreciation: equity.appreciation
}
console.log(reportObj)
let url = "http://localhost:3000/reports"
fetch(url, {
method: 'POST',
headers: {
// "Accept": "application/json",
'Content-Type': 'text/plain',
},
body: JSON.stringify({report: {reportObj}})
}
)
.then(res => res.json())
.then(res => console.log(res))
}
My backend controller looks like this:
class ReportsController < ApplicationController
def index
reports = Report.all
render json: reports
end
def show
report = Report.find(params[:id])
render json: report
end
def create
# binding.pry
report = Report.create(report_params)
render json: report
end
private
def report_params
params.require(:report).permit(:purchase_price, :monthly_rent,
:annual_rent_appreciation, :annual_property_taxes,
:annual_property_repairs, :annual_vacancy_rate,
:loan_years, :loan_rate,
:exit_year, :property_appreciation
)
end
end
My cors is enabling all data ( i think):
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
And my routes are:
Rails.application.routes.draw do
# For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
resources :properties
resources :reports
end
The error that i'm getting in my terminal is :
ActionController::ParameterMissing (param is missing or the value is empty: report):
app/controllers/reports_controller.rb:21:in `report_params'
app/controllers/reports_controller.rb:15:in `create'
And the error in the console is :
enter image description here
///EDITED:
the data is being passed to the server, however it does not save the record- i have no idea why,
Can anyone help with this issue ?
enter image description here
Don't understand why the id is null, what am i doing wrong?
The frontEnd still gives me the following erorr:
enter image description here

ReactJS API request failing

I am developing a react app using Spring Boot backend.
I am not very friendly with Java or Spring Boot and now I am stuck with an issue.
Bellow is backend method code which is handling the request
#RestController
#RequestMapping("/toys")
public class ToysController {
#Autowired
private ToysService toysService;
#CrossOrigin(origins = "*")
#PostMapping("/addtoy")
public ResponseEntity<Toys> addToy(#RequestParam("file") MultipartFile file,
#RequestParam("toyName") String toyName,
#RequestParam("toyDescription") String toyDescription,
#RequestParam("toyPrice") Long toyPrice,
#RequestParam("quantity") int quantity,
#RequestParam("availability") Boolean availability,
#RequestParam("sellerId") Long sellerId) throws IOException{
Toys toy = new Toys();
toy.setToyName(toyName);
toy.setToyDescription(toyDescription);
toy.setQuantity(quantity);
toy.setToyPrice(toyPrice);
toy.setAvailability(availability);
toy.setSellerId(sellerId);
toy.setToyImage(ImageEncoderDecoder.compressBytes(file.getBytes()));
toy.setImageName(file.getOriginalFilename());
Toys toyRes = toysService.addToy(toy);
if(toyRes!=null) {
toyRes.setToyImage(ImageEncoderDecoder.decompressBytes(toyRes.getToyImage()));
return new ResponseEntity<Toys>(toyRes,HttpStatus.OK);
}
else {
return new ResponseEntity<Toys>(HttpStatus.NO_CONTENT);
}
}
}
Below are the request details I am supposed to use
API: http://localhost:8081/toys/addtoy
Method: POST
Body:
[{"key":"toyName","value":"Car","type":"text","enabled":true},
{"key":"toyDescription","value":"small car 6 month old","type":"text","enabled":true},
{"key":"toyPrice","value":"600","type":"text","enabled":true},
{"key":"quantity","value":"2","type":"text","enabled":true},
{"key":"availability","value":"true","type":"text","enabled":true},
{"key":"file","type":"file","enabled":true,"value":[]},
{"key":"sellerId","value":"1","type":"text","enabled":true}]
Response: Status code 200
Following is how I am trying to hit the API
export const addToy = toy => {
const requestOptions = {
mode: 'cors',
method: 'POST',
headers: {
"Content-Type": "multipart/form-data; boundary=%%",
'Access-Control-Allow-Origin' : '*'
},
body: toy
};
fetch(`${API}/toys/addtoy`, requestOptions) // API = 'http://localhost:8081'
.then(response => {
if(response.status === 200)
console.log('Toy Inserted');
console.log('Resopose : ', response);
})
.catch(err => {
console.log('Error while inserting toy : ', err);
})
}
Calling the above method
const handleSubmit = e => {
e.preventDefault()
let formData = new FormData()
formData.append('toyName', toyName)
formData.append('toyDescription', toyDesc)
formData.append('toyPrice', parseInt(toyPrice))
formData.append('quantity', parseInt(toyQty))
formData.append('availability', parseInt(toyQty) > 0)
formData.append('file', image)
formData.append('sellerId', parseInt(loggedIn.loggedInUser.userId))
addToy(formData)
}
The response I am getting back
body: ReadableStream
locked: false
bodyUsed: false
headers: Headers {}
ok: false
redirected: false
status: 400
statusText: ""
type: "cors"
url: "http://localhost:8081/toys/addtoy"

Cookie not set in chrome even when React app is served from the same port as Spring Boot

I have an application running on http://localhost:8181/ which has React integrated with Spring Boot. (both run on the same port).
I send this POST request to http://localhost:8181/public/authenticate using axios:
The axios instance:
export const axios_register_login_user = axios.create({
baseURL: '/public',
withCredentials: true,
headers: { "content-type": "application/json" },
method: 'POST'
})
The login request:
export async function login(username, password, callback) {
axios_register_login_user.post("/authenticate", {
'username': username,
'password': password
}).then(response => {
console.log("success", response);
callback(response.data);
}).catch(error => {
console.log("failed", error);
callback("Failed");
})
}
The login is successful and I can see a cookie being returned in the response
However, this cookie is not set in the Application->Cookies tab
Here's my API code:
#RequestMapping(value = "/authenticate", method = RequestMethod.POST, produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public ResponseEntity<?> authenticateUser(#RequestBody AuthenticationRequest request, HttpServletResponse response) {
try {
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword());
authenticationManager.authenticate(usernamePasswordAuthenticationToken);
} catch (BadCredentialsException e) {
throw new BadCredentialsException("Invalid details");
}
UserDetailsImpl userDetails = (UserDetailsImpl) userDetailsService.loadUserByUsername(request.getUsername());
String name = userDetails.getUser().getName();
String generatedToken = jwtUtil.generateToken(userDetails);
Cookie cookie = new Cookie("jwt", generatedToken);
cookie.setMaxAge(60 * 60 * 10);//like JWT, the max age is 10 hours
// cookie.setSecure(false);
cookie.setHttpOnly(true);
response.addCookie(cookie);
return new ResponseEntity<>(new AuthenticationResponse(name + " " + generatedToken), HttpStatus.OK);
}
I tried adding
#CrossOrigin(allowCredentials = "true", origins = "{http://localhost:3000,http://localhost:8181}")
to the above method but it didn't help.
Please help me out with this. I've been stuck here for 2 days now :(
I was missing cookie.setPath("/") in my code.
Additionally, I also did cookie.setSecure(false);
After these changes, the cookie was added to the browser

SalesForce Create Lead Rest Api

My task is pretty simple, all i have to do is to create records in the lead section of the salesforce. I have created a free account and i am not able to figure it out that, what is https://yourinstance.saleforce.com in the below rest api:
https://yourinstance.salesforce.com/services/data/v39.0/sobjects/Lead
Body JSON:
{
"body": {
"Salutation": "Mr.",
"FirstName": "H",
"LastName": "Sam",
"Company": "Samosto"
}
}
Header:
Authorization: Bearer 00D0o0000015jPn!ARgAQPiIGhuYGUG_c0HDKNR0hxTX9zS82Fv1lIuqn4rapFJHPR422gLyi10rF8Auukb._hj9pj532DP7IajQV36lyKpUNEXdxvL
Content-Type: application/json
Sforce-Auto-Assign: TRUE
Any help will be highly appreciated!
This is the URL you have for the organization you want to login to. Since most of the orgs are using their own Domain names in guides or examples you will see this "https://yourinstance.saleforce.com" being used.
You can simply take it from the URL while logged in Salesforce or go to Setup -> quick search "My Domain" and you will see the domain name.
It is a good thing to check it from here as the generic URL can also be blocked as a login option.
fwiw i think the API has changed to Account. This is working for me
// to run:
// node create_new_account.js --config ./config_na150_scan_email_app.json
//
// links:
// https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_sobject_create.htm
const axios = require("axios");
const qs = require("qs");
const yargs = require("yargs");
const argv = yargs
.command('create_account', 'test creating salesforce leads', {
config: {
description: 'config',
alias: 'c',
type: 'string',
}
})
.help()
.alias('help', 'h')
.argv;
let { salesforce, scanResultsURL } = require(argv.config);
const auth_data = qs.stringify({"username": salesforce.username,
"password": salesforce.password + salesforce.security_token,
"grant_type": "password",
"client_id": salesforce.consumer_key,
"client_secret": salesforce.customer_secret,
"redirect_uri": salesforce.redirect_uri});
console.log("auth data", auth_data)
const auth_config = {
method: "post",
url: salesforce.oauth2_uri,
data: auth_data,
headers: {"Content-Type": "application/x-www-form-urlencoded"}
}
const action_url = "https://na<TBD>.salesforce.com/services/data/v51.0/sobjects/Account"
console.log('action url', action_url)
data = {
"Name" : "test Salesforce account API"
}
async function createAccout() {
// "get" token
axios(auth_config).then(function (response) {
auth_header = {"Authorization": "Bearer " + response["data"]["access_token"]}
action_config = {
method: "post",
url: action_url,
headers: auth_header,
data: data
}
// use valid token to send email
axios(action_config).then(function (response) {
console.log("action response", response["data"]); // TODO rm
}).catch(function (error) {
console.log("authenticated passed, action failed")
console.log("action error", error); // TODO something
})
}).catch(function (error) {
console.log("action token error", error); // TODO something
})
}

gmail API for sending users messages in nodejs javascript failes

My nodejs program fails to send messages using the Gmail api.
The solution from Gmail API for sending mails in Node.js does not work for me.
I encode an email with
var {google} = require('googleapis');
// to and from = "some name <blaw.blaw.com"
function makeBody(to, from, subject, message) {
var str = ["Content-Type: text/plain; charset=\"UTF-8\"\r\n",
"MIME-Version: 1.0\r\n",
"Content-Transfer-Encoding: 7bit\r\n",
"to: ", to, "\r\n",
"from: ", from, "\r\n",
"subject: ", subject, "\r\n\r\n",
message
].join('');
encodedMail = new Buffer(str).toString("base64").replace(/\+/g, '-').replace(/\//g, '_');
return encodedMail;
}
Then go to the Google API explorer
https://developers.google.com/apis-explorer/#p/
enter gmail.users.messages.send and the string generated from the above make_body.
An email will be successfully sent. So I know the above encoding is
ok.
When my program tried to send using the following, it fails with error
Error: 'raw' RFC822 payload message string or uploading message via
/upload/* URL required
function sendMessage(auth) {
var gmail = google.gmail('v1');
var raw = makeBody('john g <asdfasdf#hotmail.com>', 'john g<asfasdgf#gmail.com>', 'test subject', 'test message #2');
gmail.users.messages.send({
auth: auth,
userId: 'me',
resource: {
raw: raw
}
}, function(err, response) {
console.log(err || response)
});
}
The auth token is good since I can call gmail.users.labels.list and I use the same authorization when using the API explorer.
Q1: Does anyone know why the above does not work?
Q2: Gmail API for sending mails in Node.js does not explain why the raw email message is wrapped inside a resource field. I tried simply raw and it did not help.
This fails.
gmail.users.messages.send({
auth: auth,
userId: 'me',
resource: {
raw: raw
}
}, function(err, response) {
console.log(err || response)
});
and so does
gmail.users.messages.send({
auth: auth,
userId: 'me',
raw: raw
}, function(err, response) {
console.log(err || response)
});
and so does this GMAIL API for sending Email with attachment
gmail.users.messages.send({
auth: auth,
userId: 'me',
data: raw
}, function(err, response) {
console.log(err || response)
});
Does anyone know where its documented how to pass the "requested body" the api explorer is asking for?
Q3: Why does the google api need substitutions in the base64 encoding?
I tried encoding using
const Base64 = require("js-base64").Base64
var encodedMail = Base64.encode(str);
When I feed this into the API explorer, I get the error
"message": "Invalid value for ByteString:
Ohai! For others that stumble here, a few things. First - we have a complete end to end sample of sending mail now here:
https://github.com/google/google-api-nodejs-client/blob/master/samples/gmail/send.js
Second, the answer above is mostly right :) Instead of installing the latest version of google-auth-library... just remove it from your package.json all together. The getting started guide was very, very wrong (it has since been fixed). googelapis brings in it's own compatible version of google-auth-library, so you really don't want to mess with that by installing your own version :)
The quickstart specifies:
npm install google-auth-library#0.* --save
When I changed this to
npm install google-auth-library -- save
it pulled in version 1.3.1 vs 0.12.0. Everything started working once I changed the code to account for the breaking changes. The latest version of googleapis also has breaking changes. Here is my tweaks to the quickstart:
package.json
....
"dependencies": {
"google-auth-library": "^1.3.1",
"googleapis": "^26.0.1"
}
quickstart.js
var fs = require('fs');
var readline = require('readline');
var {google} = require('googleapis');
const {GoogleAuth, JWT, OAuth2Client} = require('google-auth-library');
var SCOPES = [
'https://mail.google.com/',
'https://www.googleapis.com/auth/gmail.modify',
'https://www.googleapis.com/auth/gmail.compose',
'https://www.googleapis.com/auth/gmail.send'
];
var TOKEN_DIR = (process.env.HOME || process.env.HOMEPATH ||
process.env.USERPROFILE) + '/.credentials/';
var TOKEN_PATH = TOKEN_DIR + 'gmail-nodejs-quickstart.json';
function authorize(credentials, callback) {
var clientSecret = credentials.installed.client_secret;
var clientId = credentials.installed.client_id;
var redirectUrl = credentials.installed.redirect_uris[0];
var auth = new GoogleAuth();
var oauth2Client = new OAuth2Client(clientId, clientSecret, redirectUrl);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, function (err, token) {
if (err) {
getNewToken(oauth2Client, callback);
} else {
oauth2Client.credentials = JSON.parse(token);
callback(oauth2Client);
}
});
}
function getNewToken(oauth2Client, callback) {
var authUrl = oauth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES
});
console.log('Authorize this app by visiting this url: ', authUrl);
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.question('Enter the code from that page here: ', function (code) {
rl.close();
oauth2Client.getToken(code, function (err, token) {
if (err) {
console.log('Error while trying to retrieve access token', err);
return;
}
oauth2Client.credentials = token;
storeToken(token);
callback(oauth2Client);
});
});
}
function makeBody(to, from, subject, message) {
var str = ["Content-Type: text/plain; charset=\"UTF-8\"\n",
"MIME-Version: 1.0\n",
"Content-Transfer-Encoding: 7bit\n",
"to: ", to, "\n",
"from: ", from, "\n",
"subject: ", subject, "\n\n",
message
].join('');
var encodedMail = new Buffer(str).toString("base64").replace(/\+/g, '-').replace(/\//g, '_');
return encodedMail;
}
function sendMessage(auth) {
var gmail = google.gmail('v1');
var raw = makeBody('xxxxxxxx#hotmail.com', 'xxxxxxx#gmail.com', 'test subject', 'test message');
gmail.users.messages.send({
auth: auth,
userId: 'me',
resource: {
raw: raw
}
}, function(err, response) {
console.log(err || response)
});
}
const secretlocation = 'client_secret.json'
fs.readFile(secretlocation, function processClientSecrets(err, content) {
if (err) {
console.log('Error loading client secret file: ' + err);
return;
}
// Authorize a client with the loaded credentials, then call the
// Gmail API.
authorize(JSON.parse(content), sendMessage);
});
Now when I run, I get the response
Object {status: 200, statusText: "OK", headers: Object, config: Object, request: ClientRequest, …}

Resources