Redirect Rule to Url Rewrite .NET Core - redirect

I am implementing AddRewrite rule in Startup.cs like this:
var rewriteOptions = new RewriteOptions()
.AddRewrite(#"^UserLogin/([0-9]+)/([_0-9a-zA-Z-]+)", "User/UserLogin?param1=$1&param2=$2", skipRemainingRules: true)
app.UseRewriter(rewriteOptions);
This works well and url is being rewritten correctly when visited: UserLogin/param1value/param2value
Now I would like to redirect old, original urls and I tried this:
var rewriteOptions = new RewriteOptions()
.AddRedirect(#"^User/UserLogin?param1=([0-9]+)&param2=([_0-9a-zA-Z-]+)", "UserLogin/$1/$2", (int)HttpStatusCode.Redirect)
.AddRewrite(#"^UserLogin/([0-9]+)/([_0-9a-zA-Z-]+)", "User/UserLogin?param1=$1&param2=$2", skipRemainingRules: true)
app.UseRewriter(rewriteOptions);
However I cannot get this to work and I cannot get the new url to work.
What am I missing here?

First the ? in your regular expression needs to be escaped as \?, since ? in regular expression means match 0 or 1 times.
But even that won't help since according to documentation of AddRedirect method what it does is
Redirect the request if the regex matches the HttpContext's PathString
Since Path string does not include query string, it won't match. And this is Evident if you look at the implementation source code
Unfortunately the implementation is internal, so you can't make a rule that inherits from RedirectRule, but since the implementation is open source, you can copy the implementation and create your own redirect rule that matches both the url and query string.

Related

nginx: rewrite a LOT (2000+) of urls with parameters

I have to migrate a lot of URLs with params, which look like that:
/somepath/somearticle.html?p1=v1&p2=v2 --> /some-other-path-a
and also the same URL without params:
/somepath/somearticle.html --> /some-other-path-b
The tricky part is that the two destination URLs are totally different pages in the new system, whereas in the old system the params just indicated which tab to open by default.
I tried different rewrite rules, but came to the conclusion that parameters are not considered by nginx rewrites. I found a way using location directives, but having 2000+ location directives just feels wrong.
Does anybody know an elegant way how to get this done? It may be worth noting that beside those 2000+ redirects, I have another 200.000(!) redirects. They already work, because they're rather simple. So what I want to emphasize is that performance should be key!
You cannot match the query string (anything from the ? onwards) in location and rewrite expressions, as it is not part of the normalized URI. See this document for details.
The entire URI is available in the $request_uri parameter. Using $request_uri may be problematic if the parameters are not sent in a consistent order.
To process many URIs, use a map directive, for example:
map $request_uri $redirect {
default 0;
/somepath/somearticle.html?p1=v1&p2=v2 /some-other-path-a;
/somepath/somearticle.html /some-other-path-b;
}
server {
...
if ($redirect) {
return 301 $redirect;
}
...
}
You can also use regular expressions in the map, for example, if the URIs also contain optional unmatched parameters. See this document for more.

nginx redirect old site urls and modify 1 language suffix only

I want to redirect old site urls to new site. But new site has different page names and language chars have changed too.
for example:
en/about/info will redirect to en/com/information
but
ge/about/info will go to ka/com/information
map $request_uri $redirect_uri {
<lang>/about/info/ $lang/com/information/
}
any ideas how I would go about this? There are a lot of urls, so I don't want to write these urls hardcoded for each language.
The map directive can capture parts of a regular expression, but cannot use that capture in the mapped result.
So it is possible to create a named capture called lang (for example) and use it after the mapped variable is evaluated. For example:
map $request_uri $redirect_uri {
~*(?<lang>/\w\w/)about/info/ com/information/;
}
And in the server or location block:
if ($redirect_uri) {
return 301 $lang$redirect_uri;
}
Note that $lang is only created after the value of $redirect_uri is evaluated in the if statement.
See this document for details.

Vertx router configuration

I am a novice with vertx so maybe I am doing something wrong. I am trying to implement the following routes:
router.get("/api/users/").handler(this::getUsers);
router.route("/api/users/:username*").handler(this::checkUsername);
router.get("/api/users/:username/").handler(this::getUser);
router.put("/api/users/:username/").handler(this::addUser);
router.get("/api/users/:username/assignments/").handler(this::getAssignments);
router.post("/api/users/:username/assignments/").handler(this::addAssignment);
router.route("/api/users/:username/assignments/:assignmentId/").handler(this::checkAssignmentId);
router.get("/api/users/:username/assignments/:assignmentId/").handler(this::getAssignment);
Is this the correct way to avoid duplicating this logic in all handlers?
I am trying to chain handlers, where the checkUsername handler reads the username parameter from the path, tries to find a corresponding user, and puts that user in the context. If no user is found, a statuscode 400 is returned. Otherwise the next handler is called. I would like to apply the same principle to the assignmentId parameter.
While trying to implement this, I believe I found a problem with the path, more specifically the trailing slash and star. The documentation states that trailing slashes are ignored. This is not the behavior when there is a parameter in the path. In that case the trailing slash matters. If the path definition contains one and the request does not, vertx returns a 404. It does not make a difference whether or not the parameter is at the end of the path or in the middle.
The same goes for paths ending with a star. This functionality does not work when the path contains a parameter.
You can use a regular expression to avoid duplication of the checkUsername validation check. What I would do is I would have a method like this to check if the username is valid:
private void checkUsername(RoutingContext routingContext){
//The "param0" is the capture group of the regular expression. See the routing config below.
if (isValidUsername(routingContext.request().getParam("param0"))){
routingContext.next();
} else {
routingContext
.response()
.setStatusCode(400)
.end();
}
}
To check the assignment ID I would do something similar:
private void checkAssignmentId(RoutingContext routingContext){
if (isValidAssignmentId(routingContext.request().getParam("assignmentId"))){
routingContext.next();
} else {
routingContext
.response()
.setStatusCode(400)
.end();
}
}
Try to avoid trailing slashes in your paths. I would change the routing handler assignments to be something like this:
router.get("/api/users").handler(this::getUsers);
//By the way, you really want to be using a POST request when adding users just to stick to the principles of REST.
//When you are sending a POST request there is no need to put the username in the URI. You can have it in the request body.
//Please ensure you validate this username using the same validation helper used in your other validations.
router.post("/api/users").handler(this::addUser);
//Use regular expression to match all "/api/users/:username*" URIs
router.routeWithRegex("\\/api\\/users\\/([^\\/]+)").handler(this::checkUsername);
router.get("/api/users/:username").handler(this::getUser);
router.get("/api/users/:username/assignments").handler(this::getAssignments);
router.post("/api/users/:username/assignments").handler(this::addAssignment);
router.route("/api/users/:username/assignments/:assignmentId").handler(this::checkAssignmentId);
router.get("/api/users/:username/assignments/:assignmentId").handler(this::getAssignment);

Optional slash in url of restfull controller

Is there a way to dynamically add a slash to your rest url?
e.g. I want to be able to generate the following rest urls in one resource.
rest/blogpost/1
rest/blogpost/1/allInfo
given the resource below, i can achieve my first url. But is there a way to make the second url with /allInfo (optional in same lResource).
lResource = $resource("../rest/blogpost/:blogId", {
Or do I need a second resource like this?
lResource = $resource("../rest/blogpost/:blogId/allInfo", {
The problem with the second $resource is that allInfo isn't optional
If you make your second argument optional using the : you can make it to work.
var lResource = $resource("rest/blogpost/:blogId/:allInfo");
lResource.query({});
lResource.query({blogId:123});
lResource.query({blogId:123,allInfo:'allInfo'});
See my fiddle http://jsfiddle.net/cmyworld/NnHr4/1/ ( See Console log)

What is a REST response, what does it do?

I had made a REST webservice using redirecting to various paths like if i need to delete some user then i will redirect the user to this address in the #Path annotation :
user/delete
and therefore there is no thing like RESPONSE i have used.
While going through a code given to me by my senior i came accross these lines :
java.net.URI uri = uriInfo.getAbsolutePathBuilder().path(id).build();
Response.created(uri).build();
What are these lines doing, i have no idea.
Can someone explain me this w/o wiki links or any other 'Basic Rest Service' links.
Without any explicit details about the uriInfo object I can only speculate its type is the JAX-RS UriInfo class.
The first line can be broken down as below:
java.net.URI uri = uriInfo.getAbsolutePathBuilder().path(id).build();
The getAbsolutePathBuilder is documented http://jackson.codehaus.org/javadoc/jax-rs/1.0/javax/ws/rs/core/UriInfo.html#getAbsolutePathBuilder%28%29
java.net.URI uri = uriInfo.getAbsolutePathBuilder().path(id).build();
The method returns a UriBuilder object. On which the 'path(...)' method is called passing the id so if the absolute path returned http://www.host.com (this may or may not have a port number) adding the id in this method will then result in the effectively Builder holding the two parts. The base URI and the path. The two values have not yet been put together
The build method then concatenates the two values resulting a full URI. For example http://www.google.com/id (Where http://www.google.com is the absolute path)
The second line
Response.created(uri).build();
Is basically saying 'Respond with a created (201) response code, and set a Location header containing the build uri value'