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.
Related
I am using Spring Cloud Gateway as an API-Gateway and also as a webserver hosting the static files (html/js/css) of an Vue.js SPA.
Preclaimer: I'm not able to change this (bad) architecture due to organisational constraints.
Currently, I'm using the default Vue Router hash mode, meaning client-side routing of the Vue app is accomplished via an URL hash like
http://hostname/#/route?parameter1=true
Because the Spring Cloud Gateway also acts as an Authentication gateway, it redirects to an OAuth2/OpenID SSO server, and by doing that, the route information of the URL hash is dropped after the redirect.
I'm trying to change this behaviour by switching to Vue Router's history mode, which would enable URLs like
http://hostname/route?parameter1=true
and therefore, routing information would "survive" SSO redirects.
To do that, Vue Router documentation includes some examples for additional Webserver configuration (like mod_rewrite for Apache etc.).
Sadly there is no example included for my very special case ;-)
I scanned the documentation of Spring Cloud Gateway, but didn't find a match for this case.
So in short:
Is it possible to configure Spring Cloud Gateway to match Vue Router's history mode requirements?
You could fix it from the Spring Boot side. I mean, you could:
Enable the Vue Router history mode like explained in the documentation here
Build a Spring Boot forwarding controller like this:
#RequestMapping(value = "{_:^(?!index\\.html|api).$}")
public String redirectApi() {
LOG.info("URL entered directly into the Browser, so we need to redirect...");
return "forward:/";
}
It basically forwards all routes to front end except: /, /index.html, /api, /api/**.
Here you can find a more detailed example.
It can be done with a custom RouterFunction:
#Bean
public RouterFunction<ServerResponse> vueHistoryModeCatchAllRoute(
#Value("classpath:/static/index.html") final Resource indexHtml) {
HandlerFunction<ServerResponse> serveIndexHtmlFunction = request -> ok().contentType(MediaType.TEXT_HTML)
.bodyValue(indexHtml);
String firstApiSegmentExcludes = "api|actuator|js|img|css|fonts|favicon\\.ico";
return route(GET("/{path:^(?!" + firstApiSegmentExcludes + ").*}"), serveIndexHtmlFunction)
.and(route(GET("/{path:^(?!" + firstApiSegmentExcludes + ").*}/**"),
serveIndexHtmlFunction));
}
This will serve the index.html (containing the Vue.js app) for all requests, which do not match one of the excluded paths (firstApiSegmentExcludes).
I have an application that was recently given an AWS certificate (and put in an ELB - classic I think).
The web application has a Flash movie that makes web calls (to same site URL) in order to fetch data using Zend Framework 1 models. The page in browser does not change.
When I request the site over https, all of the imported items have been changed over to https protocol, but when the Flash movie initializes, it makes non-secure requests over http.
It makes these non-secure requests when I load the site over http, or https.
The reason I mentioned the AWS ELB is because I was told that the ELB is doing some kind of redirect to port 80.
If I request the site over https, and immediately do print_r on $_SERVER array I am only seeing HTTPS as a REDIRECT key, and not seeing $_SERVER['HTTPS'] set, which I think is important.
In summary, the Flash movie, inside a Zend 1.12 site, is making POST requests over http, and I'd like it to make the same requests, but over https.
It is a very old Flash movie, and although I've opened the swf file with a decompiler, I do not know much about actionscript to see where (in the many code files) I'd be able to instruct the movie to call https instead of http.
My theory is that when the site is properly running as SSL/https that the flash movie may ?possibly? start making https calls since at the moment is "is" using the address bar URL, but there also could be that ELB redirect stuff happening that's gumming it up as well.
Update: I found (what appears to be) evidence that if https is detected in the URL it's given, that it will then make secure requests...
FILE: mx.rpc.remoting.RemoteObject
mx_internal function initEndpoint() : void
{
var chan:Channel = null;
if(endpoint != null)
{
if(endpoint.indexOf("https") == 0)
{
chan = new SecureAMFChannel(null,endpoint);
}
else
{
chan = new AMFChannel(null,endpoint);
}
channelSet = new ChannelSet();
channelSet.addChannel(chan);
}
}
Thanks,
Adam
I was able to restore the original/old unedited Flash SWF File, and instead modified the PHP Code that passes in a variable and value called "endpoint".
In the code sample I provided, it checks if endpoint has https in it (which I initially thought that it did).
I added code to modify the value of "endpoint" when HTTP_X_FORWARDED_PROTO was "https", sample below: (the $request->getBaseUrl() is from Zend Framework).
if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
$endpoint = sprintf(
'%s://%s%s',
$_SERVER['HTTP_X_FORWARDED_PROTO'],
$_SERVER['HTTP_HOST'],
$request->getBaseUrl()
);
} else {
// use existing (and working) value for endpoint
}
With that code in place, the FLASH movie loads in, and operates properly
whether site is loaded with http or with https
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.
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.