Custom directive that needs the request context?

234 views
Skip to first unread message

Timothy Perrett

unread,
May 7, 2013, 12:55:11 AM5/7/13
to spray...@googlegroups.com
Hey all,

I have a custom directive that looks like:

  def myCustomThing: Directive[MyThing :: HNil] = 
    (optionalHeaderValueByName("foo") &
    optionalHeaderValueByName("bar")).hmap {
      case foo :: bar :: HNil => 
        foobarthing(foo, bar)(ctx.request) // this needs to be here, but clearly has to come from somewhere?? 
    }

The foobarthing method returns a HttpRequest => MyThing, but i'm not sure how to thread the RequestContext into the directive definition... i've seemingly tried everything at the moment but cant fathom it at this hour of the day. Passing it as a argument confused the compiler in the route definition usage :-(

Any suggestions? 

Cheers, Tim 

Mathias

unread,
May 7, 2013, 3:38:45 AM5/7/13
to spray...@googlegroups.com
Tim,

your questions boils down to "How do I use the `directive.hmap`?".
This is how it works:

`hmap` is essentially the same as a regular `map`, only that it works on HLists rather than single values. We prefix methods working on HLists with a single `h` character so as to free up the name-space for the simple `map` and `flatMap` methods, that work on single-element HLists without requiring the little bit of HList boilerplate.

In your case you have a directive extracting two values (`optionalHeaderValueByName("foo") & optionalHeaderValueByName("bar")`) and you appear to want to map them.
This is how you do it:

underlyingDirective.hmap {
case foo :: bar :: HNil => expressionCreatingAnotherHList
}

All you need to do is to map an HList instance to another HList instance. In your case you apparently want to reduce the two values into a single one, so the whole thing would look like this:

underlyingDirective.hmap {
case foo :: bar :: HNil => foobarthing(foo, bar) :: HNil
}

> The foobarthing method returns a HttpRequest => MyThing, but i'm not sure
> how to thread the RequestContext into the directive definition…

What does foobarthing(…) logically do?
Does it extract a value from the request or create something you'd like to respond with?

In the first case you'll have to `hflatMap` rather than `hmap`:

underlyingDirective.hflatMap {
case foo :: bar :: HNil => extract(ctx => foobarthing(foo, bar)(ctx.request))
}

HTH and cheers,
Mathias

---
mat...@spray.io
http://spray.io
> --
> You received this message because you are subscribed to the Google Groups "spray-user" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to spray-user+...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Timothy Perrett

unread,
May 7, 2013, 1:35:42 PM5/7/13
to spray...@googlegroups.com
Sure thing, I already had tried the hFlatMap solution... the key part I was missing there was the "extract" call. Thanks!

Although, how can I reject from within that block? If i satisfy the compiller I get warnings inside the output that says its not able to complete an already handled / rejected request. 

E.g:

 underlyingDirective.hflatMap { 
      case foo :: bar :: HNil =>  
        extract {
          foobarthing(foo, bar)(ctx.request) match {
            case Good => <return type>
            case Bad => ctx.reject(...) // not compile time valid
          }
        } 
    } 

Thanks

Timothy Perrett

unread,
May 7, 2013, 1:49:37 PM5/7/13
to spray...@googlegroups.com
Managed to get it working with the following:

extract { ctx => foobarthing(a, b)(ctx.request) 
          }.flatMap { 
            _ match {
              case Good(x) => provide(x)
              case AuthResult(_, cc)  => reject(...)
            }
          } 

Thanks!

Mathias

unread,
May 8, 2013, 10:12:47 AM5/8/13
to spray...@googlegroups.com
Tim,

glad you figured it out.

Note that you can shorten your code to this:

extract { ctx => foobarthing(a, b)(ctx.request) } flatMap {
case Good(x) => provide(x)
case AuthResult(_, cc) => reject(...)
}

Cheers,
Reply all
Reply to author
Forward
0 new messages