I have several get routes for my akka-http service; they all have the form:
pathPrefix("compass") {
path("route") {
parameters(('srclat.as[Double], 'srclon.as[Double],
'destlat.as[Double], 'destlon.as[Double])) {
(srclat, srclon, destlat, destlon) =>
complete(getRoute((LatLong(srclat, srclon), LatLong(destlat,
destlon))))
}
}
}
Using Cats Validated data type, I am able to validate both the latitudes and longitudes passed to the method, collecting any values that exceed their ranges in a List[String]. I know there's a validate directive, but I'm not sure if it works for applicative (accumulative) style validation (so if multiple parameters are wrong, I'll get a list of all errors), but I'm not sure how to use the validate directive for this, or if there's a preferred way.
Also, I know parameters is a directive and should be able to be reused-- I have 3 get methods with the same parameters (requiring the same validation), so if there's a way to accomplish this with the least amount of boilerplate, that would be great. Thanks for any suggestions!
Related
I'm using Loopback 3.x with loopback-connector-mongodb 3.x
Apparently, many built-in endpoints can take a filter parameter which can be defined as JSON and it may contain complex filter conditions like order, where, skip etc.. For example:
GET /api/activities/findOne?filter={"where":{"id":1234}}
However, although Loopback uses an ORM, it seems the request parameters are passed to mongodb without any kind of pre-processing or escaping.
I was unable to find any Loopback API method which could help me make the value safe.
If, for example, the user puts Javascript into the where filter, or adds unsupported characters (such as null char), the app throws an exception an exits.
I'm sure I'm missing something here. What's the best way to make the value passed in filter={...} safe?
Is there a built-in API method for this?
If there isn't, are there any node module I could use?
Thanks for the help guys!
I turned off Javascript in MongoDB and wrote a little middleware to handle escaping. This is registered in middleware.json and thus it runs before every request and escapes the values.
module.exports = function createEscaper(options) {
return function queryEscape(req, res, next) {
if (req.query.filter) {
// escape various things and update the value..
}
next();
};
}
But I find it really strange that neither the MongoDB connector nor Loopback itself provides any solution for this. I mean, these parameters are defined and handled in framework code. It's kinda crazy there is no built-in escaping whatsoever.
You can create a mixin which validates the JSON you receive.
For example:
module.exports = function(Model, options) {
Model.beforeRemote('find', (ctx, instance, next) => {
// Validate the filter object
}
}
I've wrote a class with some functions that does HTTP calls and returns a Future[String]. I use those functions inside a method that I need to write some tests:
def score(rawEvent: Json) = {
httpService
.get("name", formatJsonAttribute(rawEvent.name))
.onComplete { op =>
op.map { json =>
//What must be tested
}
}
}
The function onComplete doesn't have a return type - it returns Unit. How can I replace that onComplete to make my function return something to be tested?
I completely agree with #Michal, that you should always prefer map to onComplete with Futures. However I'd like to point out that, as you said yourself, what you wish to test is not the HTTP call itself (which relies on an HTTP client you probably don't need to test, a response from a server on which you may have no control, ...), but what you do with its answer.
So why not write a test, not on the function score, but on the function you wrote in your onComplete (or map, if you decided to change it)?
That way you will be able to test it with precise values for json, that you may wish to define as the result you will get from the server, but that you can control completely (for instance, you could test border cases without forcing your server to give unusual responses).
Testing that the two (HTTP call and callback function) sit well together is not a unit-test question, but an integration-test question, and should be done only once you know that your function does what is expected of it.
At that time, you will effectively need to check the value of a Future, in which case, you can use Await.result as #Michal suggested, or use the relevant constructs that your test framework gives. For instance, scalatest has an AsyncTestSuite trait for this kind of issue.
Use map instead of onComplete. It will also provide you with resolved value inside mapping function. The return type of score function will be Future[T] where T will be the result type of your processing.
In the tests you can use scala.concurrent.Await.result() function.
In a friendly chat that I was having with a friend during a code review we notice that in the code there was a lot of:
unknownTypeVal match {
case asStr: String => //DO SOMETHING FOR STRING
case asInt: Integer => //DO SOMETHING FOR Integer
case asMyOwnClass: MyOwnClass => //DO SOMETHING FOR MyOwnClass
}
problem that was initially generated by methods that return Any or Option and there is no way to remove that because we are using libraries as XPath, and JSONPath, which return instances of Any or Option for a provided path.
I don't want to get into discussions of "preference", this is not an opinion question, I want to know either by standard defined preferably by Scala, or any other organization of impact, to do this kind of "type checking" in code in a more organized way, we think that this functionality can be reduced to a single function call to a method which contains a map of function and based on "something" (name of the class or something else that I do not know right now) determine how to process such parameter:
process(myAnnonimusVal: Any) = myMapOfFunct(myAnnonimusVal.getClass) //and based on the function that this will return execute such function pasing myAnnonimusVal
what is encouraged to do by Scala devs or Scala community
In principle, match is the cleanest way to execute code conditional on matching the Any type to something else. Any chain of if-else, instanceOf, etc is bound to turn out to be even more cumbersome and less elegant. A possible exception is a case where you know what the actual type is and can act accordingly, where a direct cast might be permissible.
That said, if you find yourself making the same matches many times, you might as well encapsulate the match in order to avoid code repetition. A partial function might be exactly what you have in mind here.
Hi scala and spray people!
I have a small annoying issue with extracting the HTTP 'Accept' header from the RequestContext and matching on it. On a normal route like so:
get {
respondWithMediaType(`text/plain`) {
complete ( "Hello World!" )
}
}
It works like a charm. But whenever I bring the context into scope like so (as suggested in the documentation for directives):
get { context => {
respondWithMediaType(`text/plain`) {
complete ( "Hello World!" )
}
} }
The result becomes the following error message:
The server was not able to produce a timely response to your request.
I am fairly new to Spray, but it looks really odd to me that bringing an (otherwise implicit) object into scope can have such a weird sideeffect. Does any of you have a clue on what is going on?
Direct access to the RequestContext is rarely needed. In fact, you only need it if you want to write custom directives. Common tasks and extracting the usual bits of data can normally be handled using one of the predefined directives.
It seems what you want to do is manual content type negotiation. In fact, you don't have to do it manually as spray does content type automatically for common data structures. Your example can be shortened to
get {
complete("Hello World!")
}
When complete is called with a string the response will always be of type text/plain. If the client would send a request with an Accept header that doesn't accept text/plain the request would already be rejected by the server.
If you want to customize the kinds of content types that can be provided from a Scala data-type you need to provide a custom Marshaller. See the documentation on how to achieve that.
Answering your original question why adding context => makes the request timeout: This is because the predefined directives already are of type RequestContext => Unit. So, writing
respondWithMediaType(`text/plain`) {
complete("Hello World!")
}
is exactly equivalent to (i.e. automatically expanded to)
ctx => respondWithMediaType(`text/plain`) {
complete("Hello World!")
}.apply(ctx)
So, if you add only ctx => manually, but don't add the apply call, an incoming request is never fed into the inner route and therefore never completed. The compiler doesn't catch this kind of error because the type of a route is RequestContext => Unit and so the variant with and the variant without the apply invocation are both valid. We are going to improve this in the future.
See the documentation for more info about how routes are built.
Finally, if you need to extract a header or its value you can use one of the predefined HeaderDirectives that simplify working with request headers a lot.
If I write a parameterized NUnit test, using something like [TestCaseSource] or [ValueSource], NUnit will pass the parameters directly to my test method. But is there any other way to access those parameters, e.g. from SetUp, or from a helper method (without having to explicitly pass the parameter value to that helper method)?
For example, suppose I have three different scenarios (maybe it's "rising rates", "falling rates", and "constant rates"). I'm writing tests for a particular calculation, and some tests will have the same behavior in all three scenarios; others in two of the three (and I'll write a second test for the other scenario); others will have a separate test for each scenario. Parameterized tests seem like a good way to model this; I can write a strategy object for each scenario, and parameterize the tests based on which scenarios each test should apply to.
I can do something like this:
public IEnumerable<RateStrategy> AllScenarios {
get {
yield return new RisingRatesStrategy();
yield return new FallingRatesStrategy();
yield return new ConstantRatesStrategy();
}
}
[TestCaseSource("AllScenarios")]
public void SomethingThatIsTheSameInAllScenarios(RateStrategy scenario) {
InitializeScenario(scenario);
... arrange ...
... act ...
... assert ...
}
The downside to this is that I need to remember to call InitializeScenario in every test. This is easy to mess up, and it also makes the tests harder to read -- in addition to the attribute that says exactly which scenarios this test applies to, I also need an extra line of code cluttering up my test, saying that oh yeah, there are scenarios.
Is there some other way I could access the test parameters? Is there a static property, similar to those on TestContext, that would let me access the test's parameters from, say, my SetUp method, so I could make my tests more declarative (convention-based) and less repetitive?
(TestContext looked promising, but it only tells me the test's name and whether it passed or failed. The test's parameters are sort of there, but only as part of a display string, not as actual objects; I can't grab the strategy object and start calling methods on it.)