Examples: query, "exact match", wildcard*, wild?ard, wild*rd
Fuzzy search: cake~ (finds cakes, bake)
Term boost: "red velvet"^4, chocolate^2
Field grouping: tags:(+work -"fun-stuff")
Escape special characters +-&|!(){}[]^"~*?:\ - e.g. \+ \* \!
Range search: properties.timestamp:[1587729413488 TO *] (inclusive), properties.title:{A TO Z}(excluding A and Z)
Combinations: chocolate AND vanilla, chocolate OR vanilla, (chocolate OR vanilla) NOT "vanilla pudding"
Field search: properties.title:"The Title" AND text
 
Answered
http client best practices or preferences?

Hello folks,

To help make the best use of HTTP clients making various POST requests to external URL, I would like to know if there are pits traps and to minimize any potentional security risk/memory leak. My background in Python or Q2 ecosystem are not strong. I'm trying to brush up my skillsets in this area. I don't know exactly how well Python handles the HTTP clients OR if I should be using Q2's classes, so here goes my questions:

  1. Does Q2 provide its own HTTP client through its factory/service classes? If so, what is it? Or do we simply just use https://docs.python.org/3/library/http.client.html and go from there?
  2. For example, I know that in .Net Framework, we have to be careful how we initialize HTTP clients as not to exhaust connection pool or create memory leak in C#- otherwise we risk bringing down the server. Does Python share same issue here? If so, what can/should I do to minimize bringing the harm to the health of Q2 servers while creating code that makes various POST requests to external API endpoints?
  3. What about handling certificate handshake? What's the preferred way of making the vendors' api endpoints trusted? I believe that we should be importing vault into the code and use that, somehow?
  4. What are the preferred timeout length before HTTP client should cancel its request? Is 1 minute sufficient? What is Q2's extension timeout default behavior from client AJAX to extension's endpoint?
  5. Similar to #4, does Python support some kind of TokenCancellation that would indicate that client user cancelled the browser request (or, in some case, maybe Q2 cancelled the request because the extension took too long for itself to complete?) This is to help short-circuit the backend logic in the extension code not to continue with its flow-logic to help not waste Q2's server resources or external third-party vendor API endpoints, if caller request got cancelled.
  6. What are the preferred way of persisting POSTED data based on user's data for a small duration of time (within 5 seconds?) To help combat users accidentially spamming API calls to the external endpoints while refreshing page.

The nature of this question is to help me make me become more informed on how to create some HTTP POST requests to various vendors API secure endpoints retrieving user data from Q2 extensions over SSL in a safe and secure way.

Edit: I should clarify, this is about backend logic in python making external requests to various API endpoints on behalf of a user (requester.)

Votes Newest

Answers 3


Dan's answer is excellent. For number 5, I suppose you come from a C# .NET background. Python does support cancellation of async functions. It works a bit different from C#, so I suggest reading up on how aync functions work in Python to understand this, I would start here and continue looking through the documentation to find what you are looking for: https://docs.python.org/3/library/asyncio-task.html

Posted 4 years ago
Trey Teter
124 × 2 Administrator
1

That's not entirely true, if you were running a bunch of simultaneous async tasks with something like asyncio.gather(), you could indeed call .cancel on the remaining tasks in the list. It's just that level of optimization is not something we typically deal with at our level. If you run into a use case that needs it, please ask another question here!

— Brian Mego   4 years ago
0

Reading asyncio-task definitely help me how it handle t hose async methods better now. Thanks!

— Rocky Smith   4 years ago

Hi Rocky,

There is definitely a lot here to cover. To start, take a look at https://docs.q2developer.com/guides/networking/web_requests.html#third-party-services .

I will address most of your points with my understanding of using the Q2 ecosystem thus far. Heads up, lots of docs incoming...

  1. Yes, the docs linked above are a great starting point, then https://docs.q2developer.com/tutorials/online_banking/q2_requests.html?highlight=q2_requests for an implementation example, and finally, https://docs.q2developer.com/api_references/q2_sdk/core/q2_requests.html?highlight=q2_requests#module-q2_sdk.core.q2_requests for module docs. Definitely take note of the "Allow list" notes in the docs. Basically, you need to let Q2 know what endpoints your logic plans to hit in production if it is an external resource, everything is blocked by default.
  2. q2_requests should handle this for you. It is built on top of https://docs.python-requests.org/en/master/
  3. The requests library should support this: https://2.python-requests.org/en/master/user/advanced/#ssl-cert-verification and q2 provides Vault storage: https://docs.q2developer.com/guides/performance_and_security/vault.html?highlight=vault
  4. https://2.python-requests.org/en/master/user/advanced/#timeouts provides some "best practice" for timeouts using the library.
  5. Sorry, I don't have a definitive answer on this one. Someone from Q2 may be able to answer this definitively.
  6. Q2 has a built in memcache service baked in: https://docs.q2developer.com/tutorials/online_banking/caching.html?highlight=cache that you could leverage for this perhaps, using the online user id as part of the key and having it live for a short duration then check it on POST?

I hope that this helps you on your journey. Honestly, the fact that you are asking these questions is great, and you are on the right track to secure and efficient extensions. Good luck!

Posted 4 years ago
1

Thanks for the awesome answers!

— Rocky Smith   4 years ago

I couldn't post this as a comment, since I exceeded 600 character, so writing this as an answer instead to Trey Teter's answer.

"Python does support cancellation of async functions," does that mean Q2 already make use of cancelling async functions for extensions? If so, do I need to write code in such ways to allow that to happen to my extension code so my extension code doesn't need to continue if its been cancelled? Or does Python already take care of that for us?
I plan to have some extension that may have various requests to vendor parties, that could take several seconds to complete.

Like I say I create an extension with python code as following (not using asyncio.gather)

async def default(self):
	await DO_REALLY_TIME_CONSUMING_REQUEST1() #take 53 second to complete. Has 2 more child tasks.
	await DO_REALLY_TIME_CONSUMING_REQUEST2() #take 85 second to complete, depends on #1 to be completed.  Has 2 more child tasks and one grand-child task in one of the child task.
	await DO_REALLY_TIME_CONSUMING_REQUEST3() #take another 53 second to complete, depends on #2 to be completed.
	await DO_REALLY_TIME_CONSUMING_REQUEST4() #take 5 minute to complete, depends on #3 to be completed.

My question is, would those tasks at the scope AND all of their child tasks in those methods be cancelled automatically if default() was given asyncio.cancel?
Going to make up a scenario, If I make a request to that endpoint, Q2 then calls that extension method, my browser thinks one minute is too long and it decides to times out the network request which ultimately cancels the request- does Q2 or Python AUTOMATICALLY cancel those pending await calls thats not yet completed, even their child tasks? Does Python automatically cancel the cascading those asyncio-tasks all the way to their children tasks, or do I need to use a token cancellation variable to cancel their child tasks if parent task got cancelled?

Posted 4 years ago