Use Flask Sockets request/ws out of context - sockets

I would like to be able to use a Flask request out of context.
I realise since Flask 0.10 there is a decorator(#copy_current_request_context) available to do that, and this is how I am using that decorator to try and modify flask-socket . Specifically the #socket.route decorator which is part of flask-sockets:
def route(self, rule, request, **options):
def decorator(f):
endpoint = options.pop('endpoint', None)
#copy_current_request_context
def do_some_work():
env = request.environ['wsgi.websocket']
self.add_url_rule(rule, endpoint, f,env, **options)
gevent.spawn(do_some_work)
return f
return decorator
Although the error this produces does make sense to me - I am assuming there's a way to do what I want.:
RuntimeError: This decorator can only be used at local scopes when a
request context is on the stack. For instance within view functions.
I tried passing the request into the decorator, but that didn't work.
To give a little more context, I am trying to add the request.environ['wsgi.websocket'] to a dict inside the Sockets object to be able to access the ws variable (which I understand to be the request environment).
On a higher level, I'd like the ability to do ws.send() from somewhere other than the #route function or view - perhaps another thread that has access to the socket object instance.
I've done something similar with Socket-IO - where the socketio object is all you need to be able to send() and recieve() data - however with Sockets it seems you need the ws object, which is the request.environ['wsgi.websocket']

Related

Scala Dynamic Variable problem with Akka-Http asynchronous requests

My application is using Akka-Http to handle requests. I would like to somehow pass incoming extracted request context (fe. token) from routes down to other methods calls without explicitly passing them (because that would require modyfing a lot of code).
I tried using Dynamic Variable to handle this but it seems to not work as intended.
Example how I used and tested this:
object holding Dynamic Variable instance:
object TestDynamicContext {
val dynamicContext = new DynamicVariable[String]("")
}
routes wrapper for extracting and setting request context (token)
private def wrapper: Directive0 = {
Directive { routes => ctx =>
val newValue = UUID.randomUUID().toString
TestDynamicContext.dynamicContext.withValue(newValue) {
routes(())(ctx)
}
}
I expected to all calls of TestDynamicContext.dynamicContext.value for single request under my wrapper to return same value defined in said wrapper but thats not the case. I verified this by generating for each request separate UUID and passing it explicitly down the method calls - but for single request TestDynamicContext.dynamicContext.value sometimes returns different values.
I think its worth mentioning that some operations underneath use Futures and I though that this may be the issue but solution proposed in this thread did not solve this for me: https://stackoverflow.com/a/49256600/16511727.
If somebody has any suggestions how to handle this (not necessarily using Dynamic Variable) I would be very grateful.

Akka-http logging request identifier

I've been using akka-http for a while now, and so far I've mostly logged things using scala-logging by extending either StrictLogging or LazyLogging and then calling the:
log.info
log.debug
....
This is kinda ok, but its hard to understand which logs were generated for which request.
As solutions for this go, I've only seen:
adding an implicit logging context that gets passed around (this is kinda verbose and would force me to add this context to all method calls) + custom logger that adds the context info to the logging message.
using the MDC and a custom dispatcher; in order to implement this approach one would have to use the prepare() call which has just been deprecated.
using AspectJ
Are there any other solutions that are more straightforward and less verbose ? It would be ok to change the logging library btw..
Personally I would go with implicit context approach. I'd start with:
(path("api" / "test") & get) {
val context = generateContext
action(requestId)
}
Then I'd would make it implicit:
(path("api" / "test") & get) {
implicit val context = generateContext
action
}
Then I would make the context generation a directive, like e.g.:
val withContext: Directive1[MyContext] = Directive[Tuple1[MyContext]] {
inner => ctx => inner(Tuple1(generateContext))(ctx)
}
withContext { implicit context =>
(path("api" / "test") & get) {
action
}
}
Of course, you would have to take context as an implicit parameter to every action. But, it would have some advantages over MDC and AspectJ - it would be easier to test things, as you just need to pass value. Besides, who said you only ever need to pass request id and use it for logging? The context could as well pass data about logged in user, its entitlements and other things that you could resolve once, use even before calling action and reuse inside action.
As you probably guessed, this would not work if you want the ability to e.g. remove logging completely. In such case AspectJ would make more sense.
I would have most doubts with MDC. If I understand correctly it has build in assumption that all logic would happen in the same thread. If you are using Futures or Tasks, could you actually guarantee such thing? I would expect that at best all logging calls would happen in the same thread pool, but not necessarily the same thread.
Bottom line is, all possible posiltions would be some variant of what you already figured out, so the question is your exact use case.

download a file with play web api (async)

I am trying to download a file using play api framework. Since all the data access layer has already been implemented with Futures I would like to get download to work with async action as well. However, the following piece of code does not work. And by not working I mean that the file sent to the client is not the same as the file on server.
val sourcePath = "/tmp/sample.pdf"
def downloadAsync = Action.async {
Future.successful(Ok.sendFile(new java.io.File(sourcePath)))
}
However, this piece works:
def download = Action {
Ok.sendFile(new java.io.File(sourcePath))
}
Any suggestion on how I can get the async method to work?
You actually don't need to use Action.async here, since Ok.sendFile is non-blocking already. From the docs:
Play actions are asynchronous by default. For instance, in the controller code below, the { Ok(...) } part of the code is not the method body of the controller. It is an anonymous function that is being passed to the Action object’s apply method, which creates an object of type Action. Internally, the anonymous function that you wrote will be called and its result will be enclosed in a Future.
def echo = Action { request =>
Ok("Got request [" + request + "]")
}
Note: Both Action.apply and Action.async create Action objects that are handled internally in the same way. There is a single kind of Action, which is asynchronous, and not two kinds (a synchronous one and an asynchronous one). The .async builder is just a facility to simplify creating actions based on APIs that return a Future, which makes it easier to write non-blocking code.
In other words, at this specific case, don't worry about wrapping your Result into a Future and just return Ok.sendFile.
Finally, both versions works as expected to me (the file was properly delivered). Maybe you are having another problem not related to how you have declared your actions.

PlayFramework instantiate object in current request scope?

I am currently active PlayFramework learner who came from world of PHP.
For example I have a Head block object in my app, which should hold title, charset encoding, meta information, etc. Something similar to Magento blocks, but without XML declaration
package blocks.Page
object Head {
var title: String = "";
}
In Application.index() method I have
blocks.Page.Head.title
Ok(views.html.application.index());
And finally in html template
#import blocks.Page.Head
<title>#Head.title</title>
However, blocks.Page.Head object is defined for entire application scope, not for single request. This object is the same for each request.
What is the right way to do, what I am trying to do? I can create container with all blocks and instantiate it with each request, then just pass to all templates. But I have a feeling that this is wrong way.
Just use usual class instead of object and pass instance to template as parameter.
Like this:
package blocks.Page
case class Head(title: String = "")
Controller:
val head = Head("Blah")
Ok(views.html.application.index(head))
And template will looks like:
#(head: blocks.Page.Head)
...
<title>#head.title</title>
I know the feeling when coming from a request-oriented language like PHP :). However, consider application-wide access as a gift of a VM (in PHP we need to go the extra mile of using some bytecode and data caching tool like APC or eAccellerator).
I would probably create a blockManager class which gives you static access to blocks by name/tag/id from the template: Block.get("MyBlock"). Then you can define and later modify your caching / storing strategy (holding in memory vs. loading from storage) without affecting your templates.

GWT: Is it OK to edit the same proxy multiple times?

I'm using GWT 2.4 with RequestFactory but not still everything is clear for me.
In this article author wrote about situation when we used an entity proxy with one instance of RequestContext and want to reuse (edit()) this entity proxy with other instance of RequestContext:
It cannot be edited because it has already a requestContext assigned.
If you want to change it you must retrieve instance of this entity
from server again
But I'm getting no exceptions when I execute this code:
RequestContext newRequest1 = factory.myRequest();
newRequest1.edit(proxy);
RequestContext newRequest2 = factory.myRequest();
newRequest2.edit(proxy);
The problems (exception) described by autor pop up when I run this version:
RequestContext newRequest1 = factory.myRequest();
MyProxy edited = newRequest1.edit(proxy);
RequestContext newRequest2 = factory.myRequest();
newRequest2.edit(edited);
So it seems that only editable copy returned by edit() is directly related with RequestContext instance.
In that case is there something wrong in approoach in which I keep one instance of (uneditable/frozen) proxy in my edit view and each time user clicks "edit" button I edit() it with new fresh RequestContext? Or should I obtain fresh instance of proxy each time too?
Getting new instance of proxy seems a bit awkward for me but I guess reusing one proxy instance may cause some issues related to sending delta of changes to server?
So to rephrase the question: it a good practice to reuse single instance of proxy with multiple RequestContexts?
There's no problem editing the same proxy twice (or more), as long as there's only a single editable instance at a time (your first code snippet should throw; if it's not then it's a bug; it could work if you don't keep references on both the RequestContext and the edited proxy).
Note that RequestFactory sends only the modified properties to the server, but it does so by diff'ing with the non-editable instance passed to edit(); so you should try to use the most recent instance as possible to keep your server-side/persisted data as close to your client-side data as possible (could seem obvious, but can lead to some surprises in practice: if you see foo on the client but have bar on the server, you'll keep the bar on the server-side until you modify the property on the client-side to something other than foo)