I am developing a backend API using Cloudflare Workers to cache the tokens into respective individual pages, something like http://cache.api/[tokenId] with token value itself as body content, using Cache API.
const tokenId = 'fakeJWT';
const internalUrl = ''.concat(
'http://cache.api/',
tokenId // the query string
);
const cacheUrl = new URL(internalUrl);
const cacheKey = new Request(cacheUrl.toString());
const cache = caches.default;
let response = new Response(tokenId);
response.headers.append('Cache-Control', 's-maxage=86400'); // 24 hours
await cache.put(cacheKey, response.clone());
I've configured Cache-Control header with 24 hours expiry. Then, I wrote another API in the same Cloudflare Workers to check the existence of the cache, it exists after 10 minutes but does not exist after 15 minutes.
const internalUrl = ''.concat(
'http://cache.api/',
tokenId // the query string
);
const cacheUrl = new URL(internalUrl);
const cacheKey = new Request(cacheUrl.toString());
const cache = caches.default;
let response = await cache.match(cacheKey);
if (!response) {
console.log(
`Cache url for ${cacheUrl} is not present`
);
return unauthorised(`${pathName}: This user session has expired! cache url is ${cacheUrl}`);
}
else
{
let response = new Response(tokenId);
response.headers.append('Cache-Control', 's-maxage=86400'); // in seconds
await cache.put(cacheKey, response.clone());
}
Did I miss anything?
What may be happening is a cache miss rather than an expiration. When using Cloudflare for caching, you shouldn't expect caching to be guaranteed, in particular using the cache API the docs mention it being data-center specific (not propagated globally) -
https://developers.cloudflare.com/workers/runtime-apis/cache/#background
Caching should be mechanism for improving performance, but not relied upon for guaranteed storage in other words. If your use-case requires this, it would be better to use the Workers Key Value -
https://developers.cloudflare.com/workers/learning/how-kv-works/
When I add bot.hears(...), it registers middleware for handling matching text messages. But now it will handle those messages even if they are sent any time, even if not expected.
So if I am creating a stateful service, I would like to listen to particular messages only at appropriate time.
How can I unregister middleware, so that it does not hear any more previously handled messages?
I turned out I was looking for Scenes. How to use them is described on Github.
I'll just post a slightly modified code from the links above:
const { Telegraf, Scenes, session } = require('telegraf')
const contactDataWizard = new Scenes.WizardScene(
'CONTACT_DATA_WIZARD_SCENE_ID', // first argument is Scene_ID, same as for BaseScene
(ctx) => {
ctx.reply('Please enter guest\'s first name', Markup.removeKeyboard());
ctx.wizard.state.contactData = {};
return ctx.wizard.next();
},
(ctx) => {
// validation example
if (ctx.message.text.length < 2) {
ctx.reply('Please enter real name');
return;
}
ctx.wizard.state.contactData.firstName = ctx.message.text;
ctx.reply('And last name...');
return ctx.wizard.next();
},
);
const stage = new Scenes.Stage();
stage.register(contactDataWizard);
bot.use(session());
bot.use(stage.middleware());
But I still don't know how to generally implement it, so I need to find it out in the Scenes code of Telegraf.
I want to ask about increase performance when i do multiple future http request in single page. In case , i want to build a dashboard page. In dashboard, i've 4 endpoints url that return different result in every endpoint and should be shown in dashboard page.
here example code when load data
var client = new http.Client();
Future main() async {
var newProducts = await client.get("${endpoint}/product?type=newly&limit=5");
ProductListResponse newProductResponse = ProductListResponse.fromJson(json.decode(newProducts.body));
var bestSeller = await client.get("${endpoint}/product?type=best-seller&limit=5");
ProductListResponse bestSellerResponse = ProductListResponse.fromJson(json.decode(bestSeller.body));
var outOfStock = await client.get("${endpoint}/product?type=out-of-stock&limit=5");
ProductListResponse outOfStockResponse = ProductListResponse.fromJson(json.decode(outOfStock.body));
var lastRequest = await client.get("${endpoint}/product-request?type=newly&limit=5");
ProductRequestListResponse productRequestResponse = ProductRequestListResponse.fromJson(json.decode(lastRequest.body));
}
every endpoint when i hit manually using postman it takes 200ms for return the result. But when i implement in flutter app, it took almost 2s.
can i improve performance when getting data?
The reason why your code run so slow is that you are making those HTTP requests one by one. Each await will take quite some time.
You can either not use await and implement the logic using callbacks (.then) or you can combine the Futures into one using Future.wait and use await for that combined Future.
Your code will look something like this:
var responses = await Future.wait([
client.get("${endpoint}/product?type=newly&limit=5"),
client.get("${endpoint}/product?type=best-seller&limit=5"),
client.get("${endpoint}/product?type=out-of-stock&limit=5"),
client.get("${endpoint}/product-request?type=newly&limit=5")
]);
I think this might be a basic question, but looking for the best approach.
I'm building an express app that should route to one of four different Mongoose models depending on the route.
Something like this:
app.get('/:trial', function(req, res){
var trial = req.params.trial;
trial.find(function(err, records) {
if (err)
res.send(err);
res.json(records); // returns all trial records in JSON format
});
});
I have 4 mongoose models named: trial1, trial2, trial3, trial4. I would like the trial parameter of the URL to determine which collection gets queried. Obviously the above won't work, but what should I do instead of rewriting the route four times instead?
Thanks in advance!
You can get models by name:
var mongoose = require('mongoose');
app.get('/:trial', function(req, res){
var trial = req.params.trial;
mongoose.Model(trial).find(function(err, records) {
if (err) {
// Return when we end the response here...
return res.send(err);
}
res.json(records); // returns all trial records in JSON format
});
});
Depending on circumstances, I would validate the value of trial first (so requesting /User doesn't dump all users to the client, for instance).
Update: Since around January 2018, it is now possible to search using the email parameter on Stripe. See the accepted answer.
I was wondering if it was possible to search a customer only by their email address when using the Stripe API.
The documentation only indicates searching by:
created,
ending_before,
limit,
starting_after
But not email.
I'd like to avoid having to list over all my customers to find which ones have the same email addresses.
Stripe now allows you to filter customers by email.
https://stripe.com/docs/api#list_customers
Map<String, Object> options = new HashMap<>();
options.put("email", email);
List<Customer> customers = Customer.list(options).getData();
if (customers.size() > 0) {
Customer customer = customers.get(0);
...
This is important to help ensure you don't create duplicate customers. Because you can't put creating a customer in Stripe and the storage of the Stripe customer ID in your system inside a single transaction you need to build in some fail safes that check to see if a particular customer exists before you create a new one. Searching customers by email is important in that regard.
I did this by using the following API request. This was not available in stripe docs.I got this by tracking down their search in the dashboard area using Browser Developer Tools.
url :https://api.stripe.com/v1/search?query="+email+"&prefix=false",
method: GET
headers: {
"authorization": "Bearer Your_seceret Key",
"content-type": "application/x-www-form-urlencoded",
}
Warning This uses an undocumented API that is specific to the dashboard. While it might work today, there is no guarantee it will continue to work in the future.
You need to retrieve and store the Stripe customer ID along with the other customer details in your database. You can then search for the email address in your database and retrieve the customer record from Stripe by using the Stripe customer ID.
UPDATE: Stripe now allows searching via email
https://stripe.com/docs/api/php#list_customers
/**
* Remember that Stripe unfortunately allows multiple customers to have the same email address.
* #see https://stackoverflow.com/a/38492724/470749
*
* #param string $emailAddress
* #return array
*/
public function getCustomersByEmailAddress($emailAddress) {
try {
$matchingCustomers = [];
$lastResult = null;
$hasMoreResults = true;
while ($hasMoreResults) {
$searchResults = \Stripe\Customer::all([
"email" => $emailAddress,
"limit" => 100,
"starting_after" => $lastResult
]);
$hasMoreResults = $searchResults->has_more;
foreach ($searchResults->autoPagingIterator() as $customer) {
$matchingCustomers[] = $customer;
}
$lastResult = end($searchResults->data);
}
return $matchingCustomers;
} catch (\Exception $e) {
Log::error($e);
return [];
}
}
You can't directly search by email.
However, you can hack a little bit to list all users, and look after your email.
Here's my code (PHP) :
$last_customer = NULL;
$email = "EmailYou#AreLooking.for";
while (true) {
$customers = \Stripe\Customer::all(array("limit" => 100, "starting_after" => $last_customer));
foreach ($customers->autoPagingIterator() as $customer) {
if ($customer->email == $email) {
$customerIamLookingFor = $customer;
break 2;
}
}
if (!$customers->has_more) {
break;
}
$last_customer = end($customers->data);
}
You only need to write this line
\Stripe\Customer::all(["email" => "YourDesiredEmail"]);
In NodeJs we can search for our desired customer with their email address like the following:
const stripeSecretKey = process.env.STRIPE_SECRET_KEY;
const stripe = require('stripe')(stripeSecretKey);
const findCustomerByEmail = async (email) => {
try {
const customer = await stripe.customers.list( {
email: email,
limit: 1
});
if(customer.data.length !== 0){
return customer.data[0].id;
}
} catch (e) {
return (e);
}
};
The actual call to stripe is using the stripe.customers.list. If the email exists in our stripe account then the returned object will contain an element called data.
Using "list()" and "search()", you can get customers by email with these Python code below:
customers = stripe.Customer.list(
email="example#gmail.com",
)
customer = stripe.Customer.search(
query="email:'example#gmail.com'"
)
You can also limit customers to get with "limit" parameter as shown below:
customers = stripe.Customer.list(
email="example#gmail.com",
limit=3
)
customer = stripe.Customer.search(
query="email:'example#gmail.com'",
limit=3
)
Since you specified that
The documentation only indicate to search by created, ending_before, limit and starting_after, but no "email".
You are right, you can't search using emails.
If you still wish to do that, What you can do instead is to get a list of all the customer and filter on the response you get using email.
For Example, in ruby you can do it as follows:
customers = Stripe::Customer.all
customer_i_need = customers.select do |c|
c.email == "foo#bar.com"
end
PS: Stripe can have multiple customers associated with one email address.
Please bear in mind when using Stripe API that it is case sensitive email (which is a bit stupid). Hopefully they change this.
Stripe API does not supports any search-by-email feature. They have this search in their dashboard but not released any to API; from the architectural concept it seems that there is no possibility or plan from stripe to include this in API; every object in their API is retrievable only by that specific objects id given by stripe while its created. May be, they have kept it as a scope for third party application developers involvement!!
So, the obvious solution is to store the customers in your own database that you want to be searchable in future - as Simeon Visser has said above
btw, for a workaround, if you already have used the stripe API a lot and there are many customer data which you now need to be searchable - the only way is to go thru the 'List all customers' functionality of API & build the database for your own purpose; ofcourse, you've to use pagination shortcut to iterate thru the whole list for doing so.
$customers = \Stripe\Customer::all(array("limit" => 3));
foreach ($customers->autoPagingIterator() as $customer) {
// Do something with $customer
}
You can try this. It worked for me. Below code will return empty list if not found data matching with email.
$stripe = new \Stripe\StripeClient("YOUR_STRIPE_SECRET");
$customers = $stripe->customers->all(['email'=>'jane.doe#example.com',
'limit' => 15,
]);
Stripe Search API Beta now is available
youtube link
Here is The Async- Await Way This Method can Be Used For All Third Party Hits with Nodejs Particularly
const configuration = {
headers: {
"authorization": `Bearer ${Your stripe test key}`,
"content-type": "application/x-www-form-urlencoded",
}
};
const requestUrl = `https://api.stripe.com/v1/search?
query=${'email you are to use'} &prefix=false`
const emailPayment = await axios.get(requestUrl,
configuration)
Axiom is Npm for creating http requests... very cool and dead simple
Stripe allows the ability to have more than once customer with the same email. That said, if you wanted to, you can pass a filters hash param to the list method to return a single customer or array of customers.
Stripe::Customer.list(email: user.email).data
The above will return an array of Stripe::Customer instances with the email