Let's say I have 1 directive for authentication. And after authentication, I would like to log. This is what I do so far:
get(...) {
myauthdirective() { v =>
myloggingdirective(v) {
...
}
}
}
So I would like to covert that to a single directive instead of having to have 2 every time I need to authenticate.
I tried using flat map, but that doesn't seem to work because authenticate returns a Directive1 and logRequestResponse returns Directive0.
// Does not work!
authenticate(myAuthMagnet).flatMap {
case ca: returnType => logRequestResponse(LoggingMagnet(logme(ca)))
}
So I tried it with map, but it doesn't seem to go into my logging magnet function.
// Does not work either!
authenticate(myAuthMagnet).map {
case ca: returnType =>
logRequestResponse(LoggingMagnet(logme(ca))) // does not go into logme function for some reason
ca
}
I also can't call logme directly because I need the request and response objects as well.
Is there a way to create a new directive with 2 directives that return different Directive types? Thanks.
There is one little thing missing in your implementation. You need to provide value after logging. So the implementation should be like:
authenticate(myAuthMagnet).flatMap {
case ca: returnType => logRequestResponse(LoggingMagnet(logme(ca))) & provide(ca)
}
Related
I need to log the raw request whenever I receive a particular post "Event" using Finch's post().
I have something like that:
val myEvent: Endpoint[String] = post("somepath" :: ipRangeEndpoint :: path[Long] :: jsonBody[Event]) {
(matchId: Long, event: Event) =>
(event match {
case _: Event.ToBeLogged =>
logger.debug(<REQUESTHERE>)
Ok("logged")
})
}
so let's say that, for a subset of cases, I need to log an incoming com.twitter.finagle.http.Request. How can I do that?
https://finagle.github.io/finch/user-guide.html#root-request
"It’s possible that Finch might be missing some of handy endpoints out of the box, especially that it’s evolved separately from Finagle. To overcome this and provide an extension point, there is a special endpoint instance, called root that returns a raw Finagle Request."
I have use case where I need to read value from query string.
Currently I have two different APIs(Some other person has created the code) which maps to same URL
GET /service/class/:className/details controllers.Student.getStudentDetails(studentId)
GET /service/class/:className/details controllers.Student.getAllStudentsDetails()
If query string is present in URL then API1 should execute, otherwise API2.
As URL is same for both APIs, I am able to hit only get-student-details API(Because it has higher priority in routes file).
I am looking for alternatives to fix this problem.
As per my knowledge we don't need to create different APIs just to handle query strings.
I am thinking to merge 2 different APIs in single APIs which takes action depending upon presence of query string in request.
What I want to know is if there is way to execute two different APIs which maps to same URL(Only difference is with query string).
NOTE: I am using play 2.4.6.
I see few ways using a single controller function (say we chose getStudentDetails)
1) Having an Option parameter:
def getStudentDetails(studentId: Option[String]) = Action { studentId match {
case Some(id) => // do something
case None => // do something else
}
// ..
}
2) Look for your query string parameters inside your http request:
def getStudentDetails = Action { request =>
request.queryString.get("studentId") match {
case Some(list) => // do something...beware this is a List
case None => // do something else
}
//...
}
Is it possible to build an enum inside a Rust macro using fields that are defined as macro parameters? I've tried this:
macro_rules! build {
($($case:ty),*) => { enum Test { $($case),* } };
}
fn main() {
build!{ Foo(i32), Bar(i32, i32) };
}
But it fails with error: expected ident, found 'Foo(i32)'
Note that if the fields are defined inside the enum, there is no problem:
macro_rules! build {
($($case:ty),*) => { enum Test { Foo(i32), Bar(i32, i32) } };
}
fn main() {
build!{ Foo(i32), Bar(i32, i32) };
}
It also works if my macro only accepts simple fields:
macro_rules! build {
($($case:ident),*) => { enum Test { $($case),* } };
}
fn main() {
build!{ Foo, Bar };
}
But I've been unable to get it to work in the general case.
It's absolutely possible, but you're conflating totally unrelated concepts.
Something like $case:ty does not mean $case is something which looks like a type, it means $case is literally a type. Enums are not made up of a sequence of types; they're made up of a sequence of variants which are an identifier followed (optionally) by a tuple structure body, a record structure body, or a tag value.
The parser doesn't care if the type you give it happens to coincidentally look like a valid variant, it's simply not expecting a type, and will refuse to parse one in that position.
What you need is to use something like $case:variant. Unfortunately for you, no such matcher exists. The only way to do something like this is to manually parse it using a recursive incremental parser and that is so out of scope of an SO question it's not funny. If you want to learn more, try the chapter on incremental TT munchers in the Little Book of Rust Macros as a starting point.
However, you don't appear to actually do anything with the cases. You're just blindly substituting them. In that case, you can just cheat and not bother with trying to match anything coherent:
macro_rules! build {
($($body:tt)*) => {
as_item! {
enum Test { $($body)* }
}
};
}
macro_rules! as_item {
($i:item) => { $i };
}
fn main() {
build!{ Foo, Bar };
}
(Incidentally, that as_item! thing is explained in the section on AST coercion (a.k.a. "the reparse trick").)
This just grabs everything provided as input to build!, and shoves it into the body of an enum without caring what it looks like.
If you were trying to do something meaningful with the variants, well, you're going to have to be more specific about what you're actually trying to accomplish, as the best advice of how to proceed varies wildly depending on the answer.
I am trying to make a wrapper for a macro. The trouble is that I don't want to repeat the same rules in both macro. Is there a way to do that?
Here is what I tried:
macro_rules! inner {
($test:ident) => { stringify!($test) };
($test:ident.run()) => { format!("{}.run()", stringify!($test)) };
}
macro_rules! outer {
($expression:expr) => {
println!("{}", inner!($expression));
}
}
fn main() {
println!("{}", inner!(test));
println!("{}", inner!(test.run()));
outer!(test);
outer!(test.run());
}
but I get the following error:
src/main.rs:8:31: 8:42 error: expected ident, found test
src/main.rs:8 println!("{}", inner!($expression));
^~~~~~~~~~~
If I change the outer macro for this, the code compile:
macro_rules! outer {
($expression:expr) => {
println!("{}", stringify!($expression));
}
}
What am I doing wrong?
macro_rules! is both cleverer and dumber than you might realise.
Initially, all input to a macro begins life as undifferentiated token soup. An Ident here, StrLit there, etc. However, when you match and capture a bit of the input, generally the input will be parsed in an Abstract Syntax Tree node; this is the case with expr.
The "clever" bit is that when you substitute this capture (for example, $expression), you don't just substitute the tokens that were originally matched: you substitute the entire AST node as a single token. So there's now this weird not-really-a-token in the output that's an entire syntax element.
The "dumb" bit is that this process is basically irreversible and mostly totally invisible. So let's take your example:
outer!(test);
We run this through one level of expansion, and it becomes this:
println!("{}", inner!(test));
Except, that's not what it looks like. To make things clearer, I'm going to invent some non-standard syntax:
println!("{}", inner!( $(test):expr ));
Pretend that $(test):expr is a single token: it's an expression which can be represented by the token sequence test. It is not simply the token sequence test. This is important, because when the macro interpreter goes to expand that inner! macro, it checks the first rule:
($test:ident) => { stringify!($test) };
The problem is that $(test):expr is an expression, not an identifier. Yes, it contains an identifier, but the macro interpreter doesn't look that deep. It sees an expression and just gives up.
It fails to match the second rule for the same reason.
So what do you do? ... Well, that depends. If outer! doesn't do any sort of processing on its input, you can use a tt matcher instead:
macro_rules! outer {
($($tts:tt)*) => {
println!("{}", inner!($($tts)*));
}
}
tt will match any token tree (see the Macros chapter of the Rust Book). $($tts:tt)* will match any sequence of tokens, without changing them. This of this as a way to safely forward a bunch of tokens to another macro.
If you need to do processing on the input and forward it on to the inner! macro... you're probably going to have to repeat the rules.
I had some success with the $($stuff: expr),+ syntax.
macro_rules! println {
( $($stuff: expr),+) => {
avr_device::interrupt::free(|cs| {
uwriteln!(unsafe { &SERIAL_STATIC}.borrow(cs).borrow_mut().as_mut().unwrap(),
$($stuff),+)
})
}
}
In the Circumflex framework, you can map an URL to a block like this:
get("/foo") = {
"hello, world!"
}
which, when browsing to /foo, will show the given string as expected. Now, to write a complete web application, you almost always need some form of authentication and authorisation. I'm trying to write some kind of wrapper for the above construct, so I can write this:
get("/foo") = requireLogin {
"hello, world!"
}
The requireLogin method would then check if the user is logged in, and if yes, execute the given block. If not, however, it should do a redirect to the login page.
Now I somehow can't get the syntax right (i'm still a Scala newbie). How would you do this in a generic fashion?
Try something like this:
def executeMaybe[A](work: => A): Option[A] =
if (util.Random.nextBoolean)
Some(work)
else
None
This executes the passed code with probability 0.5, returning Some(<result delivered by work>), or returns None is the other cases. You can call it either like this:
val v = executeMaybe(42)
or with block notation:
val v = executeMaybe {
// do some work
// provide return value
}
The trick is to use a by-name parameter, signalled by the => symbol. Read more e.g. here: http://daily-scala.blogspot.com/2009/12/by-name-parameter-to-function.html
The way I asked it, Jean-Philippe's answer is correct.
But here's some information specific to Circumflex:
In the Circumflex RequestRouter, the following can be used to implement the required method:
def requireLogin (f: => RouteResponse ): RouteResponse = {
if(loggedIn) {
return f
}
else {
return sendRedirect("/login")
}
}
The reason behind this was getting clear with the hint from Jean-Philippe's answer, and once I remembered that the following call isn't an assignment of a block to some internal data, but is mapped to another method call instead.
So, the call
get("/") = {...}
is actually mapped to this:
get.update("/", {...})
The block is passed in as a By-Name parameter, so the return value of requireLogin must be the same - which, for Circumflex, is RouteResponse, and not a function.
You also can use j2ee container authentication with <login-config> and <security-constraint> stuff inside web.xml