Apache Camel - Problems with Node.js - apache

So I have 100 different things going wrong in a piece of code. I recently switched from Apache and PHP to Node.js. I have a particular piece of code that merely duplicates a request that it receives. Basically, my web app posts a JSON request to my server (PHP or Node.js), then the server sends the exact same request to my Apache Camel configuration. In PHP, this worked perfectly. When switching to Node.js, I'm getting errors from Apache Camel.
Specifically, I have a piece of code that sends the exact same request twice almost instantaneously (I know how to fix it, just bear with me). In PHP, this code would work fine. In Node.js, the first request works fine, but the second one fails. Apache Camel receives a request with an empty body the second time. And to be honest, I'm 100% clueless.
What exactly could be going wrong here? Logic tells me that if it worked with PHP but not Node (same Camel code) that it has to be an issue with Node.js. But I had to mention Camel just in case, because Camel does a few weird things with requests sometimes.
I'm going to post my code below and maybe you can see an issue. I've been working on this for 3 days (on and off) and haven't found a problem yet. Also, bear in mind that I just started using node a few days ago.
PHP
<?php
require_once("globals.php");
//There's nested JSON here so I could include the destination address
$request = file_get_contents('php://input');
$json = json_decode($request);
$urlid = $json->{"urlid"};
$json = $json->{"data"};
if (session_start() === FALSE)
{
echo "{ \"postsuccess\": false, \"error\": -1 }";
return;
}
if(!isset($_SESSION["username"]) ||
!isset($_SESSION["expirationdate"]) ||
!isset($_SESSION["securitytoken"]) ||
$_SESSION["expirationdate"] <= time())
{
echo "{ \"postsuccess\": false, \"error\": -2 }";
return;
}
if(strtolower($_SESSION["username"]) != strtolower($_COOKIE["UserNameCookie"]))
{
echo "{ \"postsuccess\": false, \"error\": -3 }";
return;
}
$json->{"securitytoken"} = strtolower($_SESSION["securitytoken"]);
$json->{"username"} = strtolower($_SESSION["username"]);
$request = json_encode($json);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $URL[$urlid]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: text/plain; charset=utf-8"));
curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
$data = curl_exec($ch);
curl_close($ch);
echo $data;
?>
Node.js (Typescript)
function handler(request: ExpressServerRequest, response: ExpressServerResponse) {
try {
var json = (request.body || JSON.parse(request.rawBody));
var security_token = request.cookies.get(global.security_token_cookie, {signed: true});
var username = request.cookies.get(global.username_cookie, {signed: true});
var urlid = json.urlid;
json = json.data;
if (!security_token || !username) {
response.send({postsuccess: false, error: -2});
return;
}
json.securitytoken = security_token;
json.username = username;
var callback = function(data) {
response.json(data);
};
db.databaseRequest(urlid, json, callback);
} catch (e) {
console.error(e.stack);
response.send({postsuccess: false, error: -1});
}
}
//Was in a different module
function databaseRequest(url: number, data: any, callback: (any) => void) {
try {
var json = JSON.stringify(data);
var headers = {
"Content-Type": "application/json",
"Content-Length": json.length
};
var options = {
host: db_host,
port: db_port,
path: url_locations[url],
headers: headers,
method: "POST"
};
var request = http.request(options, function(response) {
response.setEncoding("utf8");
var returnData = "";
response.on("data", function(d) {
returnData += d;
});
response.on("end", function() {
if (returnData) {
callback(JSON.parse(returnData));
} else {
callback(null);
}
});
});
request.on("error", function(e) {
console.error("Error posting database request:");
console.error("Location: " + url_locations[url]);
console.error("Data: " + json);
console.error("Error Event: " + e);
});
request.write(json);
console.log("Sending: " + json + " to " + url_locations[url]);
request.end();
} catch (e) {
console.error(e.stack);
request.end();
callback({ "dberror" : true });
}
}

EDIT:
I'm going to keep this updated, but I honestly doubt anybody but me will ever have this issue. :/
I found the root of the problem. It turned out to be a concurrency issue. PHP submitted the requests linearly, while Node.js is non-blocking, so it send requests before the others got back. Essentially, I was dumb enough to store state information in a processor. My routes look something like this:
from("jetty:http://foo").process(new WorkProcessor()).to("direct:foo2");
My initial thinking was that "OK, a new WorkProcessor is created every time the route is triggered, so each message gets its own little sandbox". Unfortunately, that's not the case, it's only created once. I don't know why I would think that, but I did. :(
So I cleared up the issue by not storing info in Processor instances. It made my code a little longer, but it solved my issue.

Related

Intervention image 405 method not found outside laravel

I used the Intervention image in my api. Then, I am trying to access it from my web, which is also Laravel but in different project. (I separated the web from the api due to some testing purposes for the api). But the image was successfully resized and saved to my public folder. But in my api there's an error then, when I comment the Image::make(), the error is gone. Why is that?
EDIT: Code from my api where I used Image::make()
$plant_image = $_FILES['image']['tmp_name'];
move_uploaded_file($plant_image, public_path()."\gallery\images\\".$_FILES['image']['name']);
$file_path = public_path() . "\gallery\images\\" . $_FILES['image']['name'];
$img = Image::make($file_path)->resize(216, 145);
$img->save();
Here is the code for the web
$(document).ready(function() {
$("form#addplant").submit(function() {
var form_data = new FormData($("#addplant")[0]);
$.ajax({
url: 'http://127.0.0.1/identificare_api/public/api/plants',
data: form_data,
type: "POST",
processData : false,
contentType: false,
success: function( json ) {
//console.log(json);
if (json.indexOf("error") > -1) {
var jsonparse = JSON.parse(json);
if(jsonparse.hasOwnProperty('error')){
location.reload(true);
alert("Code: " + jsonparse.error.code + "\n" + "Message: " + jsonparse.error.message);
}else{
location.reload(true);
alert("Please fill in empty fields");
}
}else{
window.location.href = "/home/"+ user_token;
alert("This item is currently under review! Please wait for admin's confirmation. Thank you!");
}
},
error: function(){
alert("Something's wrong with your api. Come on fix it!");
}
});
});
});

Got problems with webhook to Telegram Bot API

Why is my webhook not working? I do not get any data from telegram bot API. Here is the detailed explanation of my problem:
I got SSL cert from StartSSL, it works fine on my website (according to GeoCerts SSL checker), but still seems like my webhook to Telegram Bot API doesn't work (despite it says that webhook was set I do not get any data).
I am making a webhook to my script on my website in this form:
https://api.telegram.org/bot<token>/setWebhook?url=https://mywebsite.com/path/to/giveawaysbot.php
I get this text in response:
{"ok":true,"result":true,"description":"Webhook was set"}
So it must be working, but it actually doesn't.
Here is my script code:
<?php
ini_set('error_reporting', E_ALL);
$botToken = "<token>";
$website = "https://api.telegram.org/bot".$botToken;
$update = file_get_contents('php://input');
$update = json_decode($update);
print_r($update); // this is made to check if i get any data or not
$chatId = $update["message"]["chat"]["id"];
$message = $update["message"]["text"];
switch ($message) {
case "/test":
sendMessage($chatId,"test complete");
break;
case "/hi":
sendMessage($chatId,"hey there");
break;
default:
sendMessage($chatId,"nono i dont understand you");
}
function sendMessage ($chatId, $message) {
$url = $GLOBALS[website]."/sendMessage?chat_id=".$chatId."&text=".urlencode($message);
file_get_contents($url);
}
?>
I don't actually receive any data to $update. So webhook is not working. Why?
Just another one moment, why your webhooks not work.
In my case the reason was in allowed_updates webhook parameter.
By calling :
https://api.telegram.org/bot<your_bot_token>/getWebhookInfo
You can see
{
"ok": true,
"result": {
"url": "<your webhook url should be here>",
"has_custom_certificate": false,
"pending_update_count": 0,
"max_connections": 40,
"allowed_updates": [
"callback_query"
]
}
}
It means, that your bot can't react to your text messages, and you will not receive any webhooks!
You can note, that "allowed_updates" contains array. So, currently it will react only to inline button events (passed as keyboard layout!). According to the setWebhook documentation, allowed_updates is an "optional" parameter.
To start receieve text messages, you need to add "message" to your "allowed_updates" prop. To do it, just again set your webhooks and add it to query. Like here :
https://api.telegram.org/bot<your_token>/setWebHook?url=<your_url>&allowed_updates=["callback_query","message"]
You will receive something like "url already added", but don't worry, allowed_updates will be updated even in this case. Just try type your message to bot and test your webhooks.
That's all, now, telegram will send webhooks to each direct message from you to your bot. Hope, it helps someone.
I was with this problem. I was trying to look everywhere and couldn't find the solution for my problem, because people were all the time saying that the problem was the SSL certificate. But I found the problem, and that were a lot of things missing on the code to interact with the telegram API webhook envolving curl and this kind of stuff. After I looked in an example at the telegram bot documentation, I solved my problem. Look this example https://core.telegram.org/bots/samples/hellobot
<?php
//telegram example
define('BOT_TOKEN', '12345678:replace-me-with-real-token');
define('API_URL', 'https://api.telegram.org/bot'.BOT_TOKEN.'/');
function apiRequestWebhook($method, $parameters) {
if (!is_string($method)) {
error_log("Method name must be a string\n");
return false;
}
if (!$parameters) {
$parameters = array();
} else if (!is_array($parameters)) {
error_log("Parameters must be an array\n");
return false;
}
$parameters["method"] = $method;
header("Content-Type: application/json");
echo json_encode($parameters);
return true;
}
function exec_curl_request($handle) {
$response = curl_exec($handle);
if ($response === false) {
$errno = curl_errno($handle);
$error = curl_error($handle);
error_log("Curl returned error $errno: $error\n");
curl_close($handle);
return false;
}
$http_code = intval(curl_getinfo($handle, CURLINFO_HTTP_CODE));
curl_close($handle);
if ($http_code >= 500) {
// do not wat to DDOS server if something goes wrong
sleep(10);
return false;
} else if ($http_code != 200) {
$response = json_decode($response, true);
error_log("Request has failed with error {$response['error_code']}: {$response['description']}\n");
if ($http_code == 401) {
throw new Exception('Invalid access token provided');
}
return false;
} else {
$response = json_decode($response, true);
if (isset($response['description'])) {
error_log("Request was successfull: {$response['description']}\n");
}
$response = $response['result'];
}
return $response;
}
function apiRequest($method, $parameters) {
if (!is_string($method)) {
error_log("Method name must be a string\n");
return false;
}
if (!$parameters) {
$parameters = array();
} else if (!is_array($parameters)) {
error_log("Parameters must be an array\n");
return false;
}
foreach ($parameters as $key => &$val) {
// encoding to JSON array parameters, for example reply_markup
if (!is_numeric($val) && !is_string($val)) {
$val = json_encode($val);
}
}
$url = API_URL.$method.'?'.http_build_query($parameters);
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($handle, CURLOPT_TIMEOUT, 60);
return exec_curl_request($handle);
}
function apiRequestJson($method, $parameters) {
if (!is_string($method)) {
error_log("Method name must be a string\n");
return false;
}
if (!$parameters) {
$parameters = array();
} else if (!is_array($parameters)) {
error_log("Parameters must be an array\n");
return false;
}
$parameters["method"] = $method;
$handle = curl_init(API_URL);
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
curl_setopt($handle, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($handle, CURLOPT_TIMEOUT, 60);
curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($parameters));
curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
return exec_curl_request($handle);
}
function processMessage($message) {
// process incoming message
$message_id = $message['message_id'];
$chat_id = $message['chat']['id'];
if (isset($message['text'])) {
// incoming text message
$text = $message['text'];
if (strpos($text, "/start") === 0) {
apiRequestJson("sendMessage", array('chat_id' => $chat_id, "text" => 'Hello', 'reply_markup' => array(
'keyboard' => array(array('Hello', 'Hi')),
'one_time_keyboard' => true,
'resize_keyboard' => true)));
} else if ($text === "Hello" || $text === "Hi") {
apiRequest("sendMessage", array('chat_id' => $chat_id, "text" => 'Nice to meet you'));
} else if (strpos($text, "/stop") === 0) {
// stop now
} else {
apiRequestWebhook("sendMessage", array('chat_id' => $chat_id, "reply_to_message_id" => $message_id, "text" => 'Cool'));
}
} else {
apiRequest("sendMessage", array('chat_id' => $chat_id, "text" => 'I understand only text messages'));
}
}
define('WEBHOOK_URL', 'https://my-site.example.com/secret-path-for-webhooks/');
if (php_sapi_name() == 'cli') {
// if run from console, set or delete webhook
apiRequest('setWebhook', array('url' => isset($argv[1]) && $argv[1] == 'delete' ? '' : WEBHOOK_URL));
exit;
}
$content = file_get_contents("php://input");
$update = json_decode($content, true);
if (!$update) {
// receive wrong update, must not happen
exit;
}
if (isset($update["message"])) {
processMessage($update["message"]);
}
?>
I had similar problem. Now solved.
The problem is possibly in a wrong public certificate. Please follow with attention instructions I propose in my project:
https://github.com/solyaris/BOTServer/blob/master/wiki/usage.md#step-4-create-self-signed-certificate
openssl req -newkey rsa:2048 -sha256 -nodes -keyout /your_home/BOTServer/ssl/PRIVATE.key -x509 -days 365 -out /your_home/BOTServer/ssl/PUBLIC.pem -subj "/C=IT/ST=state/L=location/O=description/CN=your_domain.com"
Telegram setWebhooks API do not check data inside your self-signed digital certificate, returning "ok" even if by example you do not specify a valid /CN! So be carefull to generate a public .pem certificate containing /CN=your_domain corresponding to your REAL HOST domain name!
It may be the SSL cert. I had the same problem: Webhook confirmed but actually SSL cert borked.
This reddit thread was helpful: https://www.reddit.com/r/Telegram/comments/3b4z1k/bot_api_recieving_nothing_on_a_correctly/
This may help who works with Laravel Telegram SDK.
I had a problem with self-signed webhook in Laravel 5.3.
After setup and getting OK result from Telegram with "Webhook was set" message, it didn't work.
The problem was related to CSRF verification. So I added the webhook url to CSRF exceptions and now everything works like a charm.
I had this problem too, after somehow the telegram didn't run my bot, so I tried to renew the certificate and set web hooks again, but again it didn't work, so I updated my VPS(yum update) and then renew my certificate and set web hooks again. after these it started working again.
This is because you are not setting the certificate like this
curl -F "url=https://bot.sapamatech.com/tg" -F "certificate=#/etc/apache2/ssl/bot.pem" https://api.telegram.org/bot265033849:AAHAs6vKVlY7UyqWFUHoE7Toe2TsGvu0sf4/setWebhook
Check this link on how to set Telegram Self Signed Certificate
Try this code. If you have a valid SSL on your web host and you have properly run the setWebhook, it should work (does for me). Make sure you create a file called "log.txt" and give write permission to it:
<?php
define('BOT_TOKEN', '????');
define('API_URL', 'https://api.telegram.org/bot'.BOT_TOKEN.'/');
// read incoming info and grab the chatID
$content = file_get_contents("php://input");
$update = json_decode($content, true);
$chatID = $update["message"]["chat"]["id"];
$message = $update["message"]["text"];
// compose reply
$reply ="";
switch ($message) {
case "/start":
$reply = "Welcome to Siamaks's bot. Type /help to see commands";
break;
case "/test":
$reply = "test complete";
break;
case "/hi":
$reply = "hey there";
break;
case "/help":
$reply = "commands: /start , /test , /hi , /help ";
break;
default:
$reply = "NoNo, I don't understand you";
}
// send reply
$sendto =API_URL."sendmessage?chat_id=".$chatID."&text=".$reply;
file_get_contents($sendto);
// Create a debug log.txt to check the response/repy from Telegram in JSON format.
// You can disable it by commenting checkJSON.
checkJSON($chatID,$update);
function checkJSON($chatID,$update){
$myFile = "log.txt";
$updateArray = print_r($update,TRUE);
$fh = fopen($myFile, 'a') or die("can't open file");
fwrite($fh, $chatID ."nn");
fwrite($fh, $updateArray."nn");
fclose($fh);
}
I had this problem too. In my case was mistake in declaring my API method. I created GET method instead of POST at first.
#api.route('/my-webhook-url')
class TelegramWebhook(Resource):
def post(self): # POST, Carl!
# ...
return response
In my case the error was due to the PHP configuration ( using cPanel )
[26-Jan-2021 09:38:17 UTC] PHP Warning: file_get_contents(): https:// wrapper is disabled in the server configuration by allow_url_fopen=0 in /home/myUsername/public_html/mydomain.com/my_bot_file.php on line 40
and
[26-Jan-2021 09:38:17 UTC] PHP Warning: file_get_contents(https://api.telegram.org/bot<my-bot-id>/sendmessage?chat_id=647778451&text=hello charlie ! k99 ): failed to open stream: no suitable wrapper could be found in /home/myUsername/public_html/myDomain.com/my_bot_file.php on line 40
so - it is pretty self explanatory.
The allow_url_fopen=0 var in the php configuration actually disables the requiered action.
But anyhow your best bet is to look at the error log on your server and see if there are any other errors in the script or server config.

limitation in the callback function in nodejs redis?

I am not sure if the issue I am having is a limitation in redis itself or in the nodejs 'redis' module implementation.
var redis = require('redis');
var client = redis.createClient(6379,'192.168.200.5');
client.on('error',function (error) {
console.log("** error in connection **");
process.exit(1);
});
client.on('connect',function () {
console.log("** connected **");
client.on('message',function (channel,message) {
if (channel == 'taskqueue') {
console.log(channel + ' --> ' + message);
var params = message.split(' ');
var inputf = params[0];
var outputf = params[1];
var dim = inputf.split('_').slice(-1)[0];
client.rpush('records',message,function (e,reply) {
});
}
});
client.subscribe('taskqueue');
});
From the code snippet above, I tried to do an RPUSH inside an "ON MESSAGE" subscription event. It does not work, and I get a client 'ON ERROR' event, thus, it prints error in connection. What is the correct way to do this?
After further searching, I came across this page https://github.com/phpredis/phpredis/issues/365 which seems to explain the scenario.

PayPal PDT SSL connection hangs up on my addon domain

On my PayPal autoReturn page with a known-to-work PHP script to accommodate Payment Data Transfer, no matter what I do I keep getting this error message: "Warning: fgets(): SSL: Connection reset by peer...*(on the line where this is: '$line = fgets($fp, 1024);'* "
Before I ask my question, let me just say that I've tried everything suggested here and in any other forum or article that I've been advised to read, e.g. changing HTTP 1.0 to HTTP 1.1, using $res=stream_get_contents($fp, 1024) instead of the while loop with $line = fgets($fp, 1024), etc., etc. My problem persists.
Here's what I think might be the problem (and I'm hoping someone can tell me if I'm on the right track): My auto return page for PDT is on an add-on site and I'm thinking that PayPal hangs up when the shared SSL (for my primary domain on a shared server) isn't recognized. So I've asked my web host for SSL to be installed specifically for my add-on domain.
Could the add-on domain SSL thing be the reason for my warning message? Again, that message is: "Warning: fgets(): SSL: Connection reset by peer...*(on the line where this is: '$line = fgets($fp, 1024);'* "
Here's my code:
//look if the parameter 'tx' is set in the GET request and that it does not have a null or empty value
if(isset($_GET['tx']) && ($_GET['tx'])!=null && ($_GET['tx'])!= "") {
$tx = $_GET['tx'];
verifyWithPayPal($tx);
}
else {
exitCode();
}
function verifyWithPayPal($tx) {
$req = 'cmd=_notify-synch';
$tx_token = $tx;
$auth_token = "MY SANDBOX AUTH_TOKEN HERE";
$req .= "&tx=$tx_token&at=$auth_token";
// post back to PayPal system to validate
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
// url for paypal sandbox
//$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
// url for payal
// $fp = fsockopen ('www.paypal.com', 80, $errno, $errstr, 30);
// If possible, securely post back to paypal using HTTPS
// Your PHP server will need to be SSL enabled.
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
if (!$fp) {
exitCode();
} else {
fputs($fp, $header . $req);
// read the body data
$res = '';
$headerdone = false;
while (!feof($fp)) {
$line = fgets($fp, 1024);
// $res=stream_get_contents($fp, 1024);
if (strcmp($line, "\r\n") == 0) {
// read the header
$headerdone = true;
}
else if ($headerdone) {
// header has been read. now read the contents
$res .= $line;
}
}
// parse the data
$lines = explode("\n", $res);
$response = array();
if (strcmp ($lines[0], "SUCCESS") == 0) {
for ($i=1; $i<count($lines);$i++){
list($key,$val) = explode("=", $lines[$i]);
$response[urldecode($key)] = urldecode($val);
}
$itemName = $response["item_name"];
$amount = $response["payment_gross"];
$myEmail = $response["receiver_email"];
$userEmailPaypalId = $response["payer_email"];
$paymentStatus = $response["payment_status"];
$paypalTxId = $response["txn_id"];
$currency = $response["mc_currency"];
// check the payment_status is Completed
if($paymentStatus!="Completed") {
payment_complete();
emailer($userEmailPayPalID);
} else {
payment_incomplete($paymentStatus);
}
/*
// check that txn_id has not been previously processed
checkIfTransactionHasAlreadyBeenProcessed($paypalTxId);
// check that receiver_email is your Primary PayPal email
checkThatPaymentIsReceivedAtYourEmailAddress($myEmail);
// check that payment_amount/payment_currency are correct
checkPaymentAmountAndCurrency($amount, $currency);
// process the order
processOrder();
} else {
exitCode();
*/
}
}
fclose ($fp);
}
I notice you're connecting to www.sandbox.paypal.com. I believe you want to connect to api.sandbox.paypal.com.

Node JS POST method with authorization

I can't find anything in the docs on exactly how to do this.
http://nodejs.org/api.html#request-method-149
I need to make a Node js POST with authorization something similar to this in ruby:
url = URI.parse('http://www.example.com/todo.cgi')
req = Net::HTTP::Post.new(url.path)
req.basic_auth 'jack', 'pass'
I am trying to essentially do this:
var client = http.createClient(80, 'http://api.foo.com');
var rq = client.request('POST', '/path/',
{
'authorization' : [account, password]
'key': value,
etc....
}
Just encode the string account:password in base64 using a Buffer and set it has header with the key Authorization, prefixed with the word Basic.
Here's an example for us more ignorant (Improvements can be made!). Works for twitter's streaming API. Listen for response and then data, as per usual when making requests.
var hackClient = http.createClient(80, 'stream.twitter.com');
var request = hackClient.request("GET", '/1/statuses/filter.json?'+querystring.stringify(params),{
"Host":"stream.twitter.com",
"Authorization":"Basic " + new Buffer('user' + ":" + 'pass').toString('base64'),
"User-Agent": "Twitter-Node"
});
request.on('response', function(response) {
response.on('data', function(chunk) {
stream.receive(chunk); //example usage, no stream object in this example exists
});
response.on('error', function(error) {
stream.emit('error', error); //again, for example
});
response.on('end', function () {
stream.emit('end');
});
});
request.on('error', function(error) {
stream.emit('error', error);
});