having a rewrite rule like this:
public class MyRule : IRule
{
public void ApplyRule(RewriteContext context)
{
var path = context.HttpContext.Request.Path;
///var controllerName = ???
}
}
how do I get the controller and action name ?
in Startup.cs /Configure I have:
var rewriter = new RewriteOptions().Add(new MyRule());
app.UseRewriter(rewriter);
app.UseStaticFiles();
app.UseMvc(
...
Rewrite Rules wont know anything about the controller and action.
It is way too early in the pipeline to know anything about MVC routing and is usually associated with rewriting to resources based on a pattern defined for the request.
URL rewriting is the act of modifying request URLs based on one or more predefined rules. URL rewriting creates an abstraction between resource locations and their addresses so that the locations and addresses aren't tightly linked.
URL rewriting is valuable in several scenarios to:
Move or replace server resources temporarily or permanently and maintain stable locators for those resources.
Split request processing across different apps or across areas of one app.
Remove, add, or reorganize URL segments on incoming requests.
Optimize public URLs for Search Engine Optimization (SEO).
Permit the use of friendly public URLs to help visitors predict the content returned by requesting a resource.
Redirect insecure requests to secure endpoints.
Prevent hotlinking, where an external site uses a hosted static asset on another site by linking the asset into its own content.
Reference URL Rewriting Middleware in ASP.NET Core
Related
I currently have two web apps that are set up in cloudflare with the following CNAMEs. Both are keystonejs applications.
app1.example.com ===pointing to ===> AWS ALB 1
app2.example.com ===pointing to ===> AWS ALB 2
I have Cloudflare Enterprise set up, so i'm able to use the "Render Override" feature in my page rules. I have 2 page rules set up using the following:
www.example.com ===render override ===> app1.example.com
www.example.com/app2/* ===render override ===> app2.example.com
Now in order to access the keystonejs application on app2.example.com. The application is called using app2.example.com/pa
The problem that i'm facing is that render override doesnt allow me to use sub paths, and i do not want to use the forwarding rule. Do i need to make my keystone application accessible through the root url, namely app2.example.com/ ? or is there another way to do this? Otherwise, would i need to use a reverse proxy? such as nginx ?
Thanks
Note: Since you are an enterprise customer, I highly recommend contacting your Customer Success Manager and/or Solutions Engineer at Cloudflare. They are there to help with exactly these kinds of questions. That said, I'll answer the question here for the benefit of self-serve customers.
I think when you say "Render Override" you actually mean "Resolve Override". This setting changes the DNS lookup for the request such that it is routed to a different origin IP address than it would be normally.
Note that Resolve Override does not rewrite the request in any way; it only routes it to a different server. So, a request to www.example.com/app2/foo will go to the server app2.example.com, but the path will still be /app2/foo (not /foo), and the Host header will still be Host: www.example.com.
It sounds like in your case you really want /app2/* to be rewritten to /pa/*, in addition to redirecting to a different origin. You can accomplish this using Cloudflare Workers, which lets you execute arbitrary JavaScript on Cloudflare's edge. Here's what the script might look like:
addEventListener("fetch", event => {
event.respondWith(handle(event.request));
});
async function handle(request) {
let url = new URL(request.url) // parse the URL
if (url.pathname.startsWith("/app2/")) {
// Override the target hostname.
url.host = "app2.example.com"
// Replace /app2/ with /pb/ in the path.
url.pathname = "/pb/" + url.pathname.slice("/app2/".length)
// Send the request on to origin.
return fetch(url, request)
} else {
// Just override the hostname.
url.host = "app1.example.com"
// Send the request on to origin.
return fetch(url, request)
}
}
With this deployed, you can remove your Resolve Override page rules, as they are now covered by the Worker script.
Note that the above script actually does rewrite the Host header in addition to the path. If you want the Host header to stay as www.example.com, then you will need to use the cf.resolveOverride option. This is only available to enterprise customers; ask your CSM or SE if you need help using it. But, for most cases, you actually want the Host header to be rewritten, so you probably don't need this.
I want to host two version of my ASP Core website on the same VPS, one for each supplied environement (Staging and Test). I would like both web sites to be accessible from a subfolder of the same URL:
http://www.mywebsite/Staging
http://www.mywebsite/Test
After reading a lot I found the following Github issue: https://github.com/aspnet/Hosting/issues/815
This tip works but for AJAX calls it crashes: Indeed, the JavaScript calls are not aware of this new path (BUG?). All requests are sent to the root base path (ignoring /Staging or /Test).
I partially solved it usig a middleware that redirects my AJAX calls to the correct path. It works for GET requests but it obviously fails for POST request that have a body.
Note that if we don't redirect, and just change the original PathBase request in the middleware, if the API call needs any authentication schema, it will throws a 401 error: The original PathBase is the root / where the response has a different path base, i.e. /Staging, then the cookie in the header prevents from this cross path base request/response.
Could someone tell me what is the recomanded practice to achieve my needs?
Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env
{
app.UsePathBase($"/{env.EnvironmentName}");
...
}
My Middleware :
public async Task Invoke(HttpContext context)
{
if (context.Request.Headers[RequestedWithHeader] == XmlHttpRequest)
{
if (string.IsNullOrEmpty(context.Request.PathBase))
{
if (context.Request.Method == HttpMethod.Post.Method)
{
// Do what ?
}
else
{
//Get request : set environement name + original path + original query string
context.Response.Redirect(context.Request.Path.ToString().Insert(0, "/" + _env.EnvironmentName) + context.Request.QueryString);
return;
}
}
}
}
Of course, your client-side code will not be able to automatically change its code based on the path base that is active for the current request. JavaScript code is (usually) static content, so unless you actually rewrite the code dynamically, it cannot update URLs that are embedded inside.
You could determine the base path from the current request’s URL but that is a rather fragile solution since you need to find a logic that will work regardless of where in the application you are. So doing so is not recommended.
The overall problem is that on the client-side, there is no concept of a path base (or even an environment). So you will have to transfer that knowledge from the server to the client. And just like the path base is set for the server-side code using the path base middleware, you will need some server-side code that will pass the path base to the client-side code.
What I personally do is just configure the root path to the API in the application layout. So my _Layout.cshtml contains the following line:
<body data-api="#Url.Content("~/api/")">
That way, I can then retrieve the root path to the API using document.body.dataset.api in JavaScript. My AJAX calls are then all made so they respect that value. That way, I can host the site at any path, and the AJAX calls will use the proper path too.
You could also just use "~" as the content path to just refer to the root of your application. And you could also expose this value in a JavaScript variable inside a <script> block instead, if you prefer that.
Using 4.0.31, my AppHost Configure method is declared like this:
public override void Configure(Funq.Container container)
{
HostConfig hc = new HostConfig()
{ HandlerFactoryPath = "api", UseHttpsLinks = true };
SetConfig(hc);
Plugins.Add(new CorsFeature());
Plugins.Add(new SwaggerFeature());
...
}
I was under the impression that this would set the url for swagger-ui to be the https version of ../api/resources, however I'm still getting the regular http endpoint in the swagger URL textbox, like:
http://example.com/myapp/api/resources
Our web servers are behind load-balancers that perform SSL offloading (and require SSL), so the URL should be:
https://example.com/myapp/api/resources
On a positive note, using 'UseHttpsLinks' actually allows swagger-ui to function once you fix the endpoint url. It didn't work at all without it!
I'm overriding the swagger url property using a replacement index.html via the Virtual File System as a hack -- since in the development, QA, and staging environments, the url property is pointing to production...(not so good)
Config.UseHttpsLinks has been expanded to also apply to the BaseUrl where it now changes http:// urls to https:// in this commit.
This change is available from v4.0.33+ that's now available on MyGet.
I'm working on a grails application that sits on a server with another root.war application. Currently we use apache redirects to hide the context path (name of our grails application) as we already have a root.war and we don't want it to show on all our urls. This works for our public content. However, now that we've added some authenticated content with spring security core plugin it always redirects to include the context path. Hence, the url /authcontent/page.gsp is getting redirected to /appname/authcontent/page.gsp. Some folks have mentioned you can remove the context path by creating a separate virtual host in tomcat, but I was wondering if there's a way to override the mechanism that Spring Security uses to do the redirect in the filter chain. Perhaps overriding the RequestCacheAwareFilter? but I believe that filter only is used after the initial authentication. I've read through the spring security documentation but it doesn't talk as much about redirecting requests as much as the whole authentication and authorization process so I'm wondering if this is in the plugin itself. Any thoughts would be helpful.
You can remove the app context in the Config.groovy file:
environments {
development {
grails.logging.jul.usebridge = true
grails.serverURL = "http://localhost:8080"
grails.app.context = "/"
}
production {
grails.logging.jul.usebridge = false
grails.serverURL = "http://yourwebsite.com"
grails.app.context = "/"
}
}
Hope that helps.
There's number of ways of doing this. Two I tried were overriding the requestCache bean (but then you also had to override the DefaultSavedRequest) and overriding the redirectStategy bean which is what I'm using as it was simpler.
My project use htaccess files to restrict access to the server resources. The access is granted with an HTTP authentication.
I want to leave HTTP authentication and use a php-session-like login authentication to check access.
What I want to do could be simply done in a script like:
<?php
session_start()
if ( !isset($_SESSION['user']) ) {
header('location : /login.php');
exit;
}
//...also we could use url rewriting to redirect all urls pointing to static resource through
// a script that will deliver its content or redirect to the login form depending on
// identification status
Using php for dynamic pages is not a problem, but how to I grand access to Static resource using a session id passed with cookies in apache ?
I've seen questions related to cookie based redirection in apache, but none of them treat about identifying a user based on a sessionId passed by cookie.
For HTML content, keep your "static" content in PHP scripts whose only "dynamic" feature is that they contain a common header included for checking login/session.
For images, css, javascript, documents, anything else, this more extensive discussion will be of help.