How Can I parse a request uri containing specific word - scala

I am trying to handle a request containing word "filter". For the time being, I am using the url as
http://localhost:9997/filter=....
and parsing by using pathPrefix(fiter)
But url will change and becomes like
http://localhost:9997/something../filter=
So here I can't take pathPrefix().
How can I handle this kind of path in routing so that any url containing "filter" keyword it can handle.
I am very much new to akka spray. Please let me know about your opinions. Thanks in advance

If the string you want to match will always be at the end you can use "pathSuffix" (it might be enough for what you want)
pathSuffix("filter") { ... }
But if it can be anywhere in the path, is not that straighforward. One way is using segments:
path( Segment / "filter" / Segment ){ (prefix, postfix) => {...} }
But it doesn't match if filter is at either end: "filter/blah/blah" nor "balh/blah/filter", but you can work around by matching with prefix and suffix. I suppose there's a better way, maybe with a custom directive.
Take a look at
http://spray.io/documentation/1.2.3/spray-routing/predefined-directives-alphabetically/#predefined-directives

Related

A simple way to iterate over paginated reponse Http4s

I'm trying to handle pagination without using string interpolation and also take advantage of http4s features.
I have came across the OptionalQueryParamDecoderMatcherand I don't know if it is a good match in my use case.
So the response contain header that has information about the number of pages in the Link attribute It has rel set to prev, next, first, or last. as follows :
<https://gitlab.example.com/api/v4/projects/8/issues/8/notes?page=1&per_page=3>; rel="prev", <https://gitlab.example.com/api/v4/projects/8/issues/8/notes?page=3&per_page=3>; rel="next", <https://gitlab.example.com/api/v4/projects/8/issues/8/notes?page=1&per_page=3>; rel="first", <https://gitlab.example.com/api/v4/projects/8/issues/8/notes?page=3&per_page=3>; rel="last"
My idea is to get the number of pages specified as last (which is the total number of pages) and then increment by one to get all the results.
The first way I thought about is string interpolation, but I believe that there would be a much simpler way to do it especially taking advantage of http4s.
Can someone enlighten me ? I'm open to your suggestions.
note: the httpRoute is specified as this example :
val routes = HttpRoutes.of[IO] {
case GET -> Root /"projects"/project_name/"Details"
}
As described in documentation you can use query matchers to extract data from query.
object Page extends OptionalQueryParamDecoderMatcher[Int]("page")
object PerPage extends OptionalQueryParamDecoderMatcher[Int]("per_page")
val routes = HttpRoutes.of[IO] {
case GET -> Root / "projects" / project_name / "Details" :? Page(page) :? PerPage(perPage) =>
...
}
OptionalQueryParamDecoderMatcherand is indeed the right usage here.
(Personally, I prefer to define API using something like Tapir or Endpoint4s (I find it saner for many reasons) and then interpret it into HTTP4s. It's a very simple way of avoiding many idiosyncrasies of HTTP4s or Akka HTTP).

Gatling. Check, if a HTML result contains some string

Programming Gatling performance test I need to check, if the HTML returned from server contains a predefined string. It it does, break the test with an error.
I did not find out how to do it. It must be something like this:
val scn = scenario("CheckAccess")
.exec(http("request_0")
.get("/")
.headers(headers_0)
.check(css("h1").contains("Access denied")).breakOnFailure()
)
I called the wished features "contains" and "breakOnFailure". Does Gatling something similar?
Better solutions:
with one single CSS selector:
.check(css("h1:contains('Access denied')").notExists)
with substring:
.check(substring("Access denied").notExists)
Note: if what you're looking for only occurs at one place in your response payload, substring is sure more efficient, as it doesn't have to parse it into a DOM.
Here ist the solution
.check(css("h1").transform((s: String) => s.indexOf("Access denied"))
.greaterThan(-1)).exitHereIfFailed
You can write it very simple like:
.check(css("h1", "Access denied").notExists)
If you are not sure about H1 you can use:
.check(substring("Access denied").notExists)
IMO server should respond with proper status, thus:
.check(status.not(403))
Enjoy and see http://gatling.io/docs/2.1.7/http/http_check.html for details
EDIT:
My usage of CSS selector is wrong see Stephane Landelle solution with CSS.
I'm using substring way most of the time :)

Perl Dancer trailing slash

Using the Perl web application framework Dancer, I am having some problems with trailing slashes in the URL matching.
Say for example, I want to match the following URL, with an optional Id parameter:
get '/users/:id?' => sub
{
#Do something
}
Both /users/morgan and /users/ match. Though /users will not. Which does not seem very uniform. Since I would prefer, only matching the URL:s without the trailing slash:
/users/morgan and /users. How would I achieve that?
Another approach is to use a named sub - all the examples of Dancer code tend to use anonymous subs, but there's nothing that says it has to be anonymous.
get '/users' => \&show_users;
get '/users/:id' => \&show_users;
sub show_users
{
#Do something
}
Note that, due to the way Dancer does the route matching, this is order-dependent and, in my experience, I've had to list the routes with fewer elements first.
id will contains everything from /user/ on until an optional slash.
get qr{^/users/?(?<id>[^/]+)?$} => sub {
my $captures = captures;
if ( defined $captures->{id} ) {
return sprintf 'the id is: %s', $captures->{id};
}
else {
return 'global user page'
}
};
I know this is an old question, but I've recently solved this problem by using a Plack middleware. There are two of them you can choose from depending on whether you prefer URLs with trailing slashes or not:
Plack::Middleware::TrailingSlash
Plack::Middleware::TrailingSlashKiller
Using any of the middleware above should greatly simplify your core Dancer application code and unit tests since you do not need to handle both cases.
In addition, as mentioned by Dave Sherohman, you should definitely arrange your routes with the fewer elements first in order to match those first, especially if you use the TrailingSlash middleware to force trailing slashes.

In Sinatra, how to make filters dependent of request method?

I've been using filters in Sinatra the way it has been declared in the documentation: with no match string, with a match string or with a match regexp. It has been working fine til now. Now, I have a particular use case. Let's say I have this route:
/resources/1
According to REST, and depending of the request method, this can either be a GET method, PUT method or DELETE method. First question is: How to write filters that are only called when it is a GET request? (currently I'm letting all of them get filtered and only then I test the method. It works, but I don't like it). Second question, and more important: let's say a PUT request like this is triggered:
/resources/
This is of course wrong, because the PUT request has no resource id associated. I would like to know if there is something in Sinatra that enables me to do something like this:
before "/resources/", :method => :put do
error_message
end
just this possibility does not exist (before accepts only one argument). How could I achieve this result at best?
Actually, filters do take conditions. You don't have to use a condition though, you could use a conditional within the filter:
before "/path/" do
if request.request_method == "PUT"
# do something
end
end
If you want to use a condition, I think you'll need to write one, perhaps something like this:
set(:accepted_verbs) {|*verbs|
condition {
verbs.any?{|v| v == request.request_method }
}
}
before "/path/", :accepted_verbs => ["GET","POST"] do
# do something
end
before "/path/", :accepted_verbs => ["PUT"] do
# do something else
end
See conditions for more.

Express Node.js framework: How to re-write a URL by replacing one of the named param segments?

In my Express app, I'd like to perform some redirects when certain params from the route match certain criteria, using a route param pre-condition. As an example, let's say I want the param word to be converted to all upper-case, if it isn't already.
The param word might be present in several different routes, e.g. /:word, /foo/:word, /foo/:word/bar, etc. Fortunately, with route param pre-conditions, these are all handled by the same code, e.g. (code in CoffeeScript):
app.param 'word', (req, res, next, word) ->
if word isnt word.toUpperCase()
new_URL = // current URL, but replace word with word.toUpperCase() //
res.redirect new_URL, 301
My question regards how to construct new_URL, replacing :word with its upper-case equivalent. I want to be able to use the same function to construct new_URL, regardless of which route is currently being used.
I see that there is req.route, but it is undefined. I guess I can access the currently matched route via req.app.routes.routes.get[req._route_index], and then split the path, and re-construct it, but that seems overly complicated. Is there a way to simply iterate the path segments for the current route? Thanks!
I ended up writing a little function to replace a named route parameter with a new value. I'm not sure this is an optimal solution, and it is not a complete solution (it definitely won't work with nob-segment named params like /:from-:to).
replaceRouteParam = (req, param, replacement) ->
segments = req.app.routes.routes.get[req._route_index].path.split('/')
new_segments = []
for segment in segments
if segment is param
new_segments.push replacement
else if segment[0] is ':'
new_segments.push req.params[segment[1..]]
else
new_segments.push segment
new_segments.join '/'
The advice I got about using this function in multiple locations (my errors, routes, etc, which are in different files) was to put them in a separate file and require it in whichever files need it.