Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HTTP message attributes #1500

Closed
gmethvin opened this issue Oct 31, 2017 · 6 comments
Closed

HTTP message attributes #1500

gmethvin opened this issue Oct 31, 2017 · 6 comments
Assignees
Labels
play-akka-http-integration t:core Issues related to the akka-http-core module
Milestone

Comments

@gmethvin
Copy link
Contributor

It would be nice if we could attach arbitrary typed values to Akka HTTP requests and responses. This could be used for things like tracking request ids/metadata, and perhaps for other things people are currently using custom headers for.

For example:

// This is a type-safe key to retrieve the attribute
// The String ID is a unique identifier for this attribute
val RequestId: Attr[UUID] = Attr("com.example.foo.bar.RequestId")

// get a new request with the RequestId attribute added
val requestWithId = request.withAttr(RequestId, UUID.randomUUID)

// get the attribute from the request
val requestId: UUID = requestWithId.getAttr(RequestId)

Ideally the API should be type safe so I can only assign an Attr[A] to a value of type A, but if it were possible to write a type-safe wrapper that would probably be sufficient.

My future use case for this would be allowing us to completely represent a Play request as an Akka HTTP request, attaching various Play metadata as attributes.

@ktoso ktoso added 1 - triaged Tickets that are safe to pick up for contributing in terms of likeliness of being accepted play-akka-http-integration t:core Issues related to the akka-http-core module labels Oct 31, 2017
@ktoso ktoso added this to the 10.0.x milestone Oct 31, 2017
@ktoso
Copy link
Member

ktoso commented Oct 31, 2017

Agreed, we currently work around this by having synthetic headers which isn't the most hygienic way to go around it and leaks sometimes.

FYI @bantonsson @jrudolph

@sarahgerweck
Copy link

This would be fantastically useful. 👍

@scr-oath
Copy link

scr-oath commented Aug 16, 2018

I was thinking it would be useful to stash values on the RequestContext so that any Directive could access/modify/extract these values to communicate with other Directives. An example is for logging - it would be great if you could set up one outer log directive over a Route.seal of all the routes unioned together with ~ and the log could look for more info on the context that was added by routes (or not) and augment what gets written accordingly. The idea being to have some sort of access-log type thing which is one line of some json-object for easy parsing by things like splunk, e.g. to be queried as desired.

Ultimately I don't care if this hangs off the RequestContext or the request (which hangs off the RequestContext), but I thought it seemed more natural to be on the context object than the request, which could be left unaltered from its initial state.

@johanandren
Copy link
Member

For me that sounds an awful lot like the request context of Servlets/JSP (or thread local for that part). Wouldn't it be better to use functional composition and explicit state passing for these kind of things than an arbitrary map of things in context?

@jrudolph
Copy link
Member

@scr-oath, the whole routing layer uses immutable data structures (aside from the streaming aspects). So, it will not be possible to mutate things in inner directive and have access to it from outer directives.

What you can do already now is to add custom headers to a request or a response:

  • Add it to the request to pass info from the outside to inside routes
  • Add it to the response to pass info from the inside to outside routes

This already works now but is a bit cumbersome because you need to define custom headers (though, note, that this is how HTTP works in general. E.g. in proxied setups, the proxies also add headers to requests and may read responses to communicate with backend servers).

This ticket describes that we want to introduce another structure, similar to custom headers that simplifies passing around information inside of Akka HTTP but the concept will exactly be the same as with custom headers.

@scr-oath
Copy link

scr-oath commented Aug 16, 2018

Ok I understand the thirst for immutable rather than the Von Neumann style. Then, I suppose this change/feature-request would be to add arbitrary objects to the request/response (not just strings) and not to the headers (because they're not destined for output)? That would really be great! FWIW, the custom headers approach does work, but is just cumbersome it seems… so this attr idea of arbitrary non-rendered stuff would be a nice addition.

@raboof raboof modified the milestones: 10.0.x, 10.2.0 Nov 15, 2019
@raboof raboof self-assigned this Jan 6, 2020
raboof added a commit that referenced this issue Jan 6, 2020
This approach follows the Play API (https://www.playframework.com/documentation/2.8.x/Highlights26)
in that you can add attributes of any user type. Otherwise it follows the
existing conventions from Akka HTTP Headers, so you can have multiple
attributes of the same type. If you want to distinguish different attributes of
the same type, like you could in Play with different keys, you would have to
introduce a wrapper type (either holding the key or creating a separate wrapper
for each key).

The main downside of this approach is that it increases the memory usage of a
message with one field.
raboof added a commit that referenced this issue Jan 6, 2020
This approach follows the Play API (https://www.playframework.com/documentation/2.8.x/Highlights26)
in that you can add attributes of any user type. Otherwise it follows the
existing conventions from Akka HTTP Headers, so you can have multiple
attributes of the same type. If you want to distinguish different attributes of
the same type, like you could in Play with different keys, you would have to
introduce a wrapper type (either holding the key or creating a separate wrapper
for each key).

The main downside of this approach is that it increases the memory usage of a
message with one field.
raboof added a commit that referenced this issue Jan 6, 2020
This approach follows the Play API (https://www.playframework.com/documentation/2.8.x/Highlights26)
in that you can add attributes of any user type. Otherwise it follows the
existing conventions from Akka HTTP Headers, so you can have multiple
attributes of the same type. If you want to distinguish different attributes of
the same type, like you could in Play with different keys, you would have to
introduce a wrapper type (either holding the key or creating a separate wrapper
for each key).

The main downside of this approach is that it increases the memory usage of a
message with one field.
raboof added a commit that referenced this issue Jan 7, 2020
This approach follows the Play API (https://www.playframework.com/documentation/2.8.x/Highlights26)
in that you can add attributes of any user type. Otherwise it follows the
existing conventions from Akka HTTP Headers, so you can have multiple
attributes of the same type. If you want to distinguish different attributes of
the same type, like you could in Play with different keys, you would have to
introduce a wrapper type (either holding the key or creating a separate wrapper
for each key).

The main downside of this approach is that it increases the memory usage of a
message with one field.
@jrudolph jrudolph added 3 - in progress Someone is working on this ticket and removed 1 - triaged Tickets that are safe to pick up for contributing in terms of likeliness of being accepted labels Jan 9, 2020
raboof added a commit that referenced this issue Feb 5, 2020
In this draft, attributes are identified by AttributeKey instance. Explicitly
naming the keys doesn't seem necessary, as they are 'internal' and never
serialized.

Refs #1500, contrast with #2872

If we decide to go with this approach we should also add directives to extract
attributes by key.
raboof added a commit that referenced this issue Feb 21, 2020
attributes are identified by AttributeKey instance. Explicitly
naming the keys doesn't seem necessary, as they are 'internal' and never
serialized.

Refs #1500

Co-authored-by: Johannes Rudolph <[email protected]>
Co-authored-by: Marcos Pereira <[email protected]>
@raboof raboof closed this as completed Feb 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
play-akka-http-integration t:core Issues related to the akka-http-core module
Projects
None yet
Development

No branches or pull requests

7 participants