WebApi: Use different Route prefix for http reservation and WebApi routes - asp.net-web-api

I have a Windows Service which exposes some APIs via WebAPI and OData using http.sys (to facilitate port sharing):
/api
/odata
/swagger
I also have reservation with http.sys for the prefix https://+:1234/.
Additionally, I have a web site (SPA) which uses this API and I'd like it to run on the same port. UP to now, this was no problem, because I had static file hosting in the service. For various reasons, I moved the static file hosting to its own service. and changed my http.sys reservation to this:
Static file hosting (Weak wildcard):
https://*:1234/
Service (strong wildcard):
https://+:1234/api/
https://+:1234/swagger/
https://+:1234/odata
And in my service I changed my
WebApp.Start("https://+:1234", Startup);
to
var options = new StartOptions
{
urls =
{
"https://+:1234/api/",
"https://+:1234/swagger/",
"https://+:1234/odata/",
}
};
_Service = WebApp.Start(options, Startup);
However, now the routes to the WebApi are https://+:1234/api/api/ and I can even use https://+:1234/api/odata/, which is kind of understandable, but not what I intended.
Can I trick WebApi that while it registers itself with http.sys on the three listening urls but always uses https://+:1234/ as the base for the routing?

This is nice question, I was tried different ways ..., But I had same experiences what you got right now....
Finally, I have understand, We can achieve your excepted out put with the UrlPrefixCollection Here is Url : https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.server.httpsys.urlprefixcollection?view=aspnetcore-2.2

Related

OpenAPI Specification 3.0 shows different url in browser and Servers dropdown

We are using OpenApi Specification v1.4.8. We have load balancer urls and domain url. Domain url http://market.place.com/productsservice/swagger-ui.html and load balancer url is http://7649263.path.aws.com/productsservice/swagger-ui.html.
Due some ongoing network issue with the domain, we have shifted to use load balancer url for testing the application. When I access swagger ui using the above load balancer url, I see the domain URL in servers dropdown(haven't added it anywhere). Thus the url in browser address bar and in Servers dropdown is different.
Since Swagger uses the base url from 'Servers' dropdown to fabricate paths for testing, and my domain is not working, I am not able to fire request from Swagger UI. The request work fine via postman when the url in browser that is load balancer url is used.
Is there some configuration which can make the Servers dropdown URL and Browser url base path same ? What we are trying to do is, the Servers dropdown needs to take the url as in the address bar of browser.
Probably you have openapi 3 configuration java class.
You should
new OpenAPI().addServersItem(...)
Edit your method like this.
private String ip="109.162.230.178"; //your ip
private String port="8587"; //your port
// if you have context add this line
private String context="tws"; //your context
#Bean
public OpenAPI customOpenAPI() {
return new OpenAPI()
.addServersItem(new Server().url("http://"+ip+":"+port+"/"+context))
...
}
now your UI Combobox is like this :
For example my server static ip is
109.162.230.178
and i have to use this Openapi 3 UI
from another computer outside of my local network in Internet.
I think of the one reason why you have this issue. You should check in code if io.swagger.v3.oas.models.servers.Server is being used in OpenAPI configuration-
OpenAPI oas = new OpenAPI();
......
......
String url = "/market.place.com/"
List<Server> servers = new ArrayList<Server>();
Server server = new Server();
server.setUrl(url);
servers.add(server);
oas.setServers(servers);
If you are relying on programmatic approach for openAPI configuration and you have something like above in your code then that may be the reason why you are seeing your domain URI. You can replace it with correct URI to make it work.

Web app with multiple domains pointing to subfolders of a parent one

I’m developing an application with Spring Boot, which runs under a domain, let’s say;
parentdomain.com
From one side the users enter their content, after logging in, at parentdomain.com/admin. This content is processed and made publicly accessible at a subfolder, let’s say;
parentdomain.com/user-one-content
parentdomain.com/user-two-content and so on.
I need to point a domain for each user to his folder, for example:
userone.com should be equivalent to parentdomain.com/user-one-content
The navigation should remain in the userone.com website.
userone.com/first-page should open parentdomain.com/user-one-content/first-page.
Right now the app is installed at PWS (Pivotal Web Services), but their routing system, doesn’t provide a solution to this approach, with multiple domains pointing to subfolders of a parent one.
How could I archive this functionality?
I would leave Spring Boot alone and put in a web server in front of it. Can you install Apache or Nginx? Domain/sub-domain rerouting is out of the box in both of them.
At the end I could archive it, thanks to the advice from gspatel
With the rooting system of PWS, or other IaaS cloud provider I can root each domain to the whole application.
Implementing the preHandle method of a HandleInterceptor, I check whether the request is coming from my domain (parentdomain.com in the example). Or if it is coming from a domain of the sites, that the app is serving (userone.com in the example). In that case, I control that doesn't access the parentdomain.com, or the content of other users, forwarding the request to the user home page (user-one-content in the example).
That's an extract, of my preHadle implementation:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
...
String URI = request.getRequestURI();
String rootURI = "/" + idweb + "/";
if(URI.equals("/") || !URI.startsWith(rootURI)){
URI = rootURI;
RequestDispatcher requestDispatcher = request.getRequestDispatcher(request.getContextPath() + URI);
requestDispatcher.forward(request, response);
}
return true;
}

Swagger page being redirected from https to http

AWS Elastic Load Balancer listening through HTTPS (443) using SSL and redirecting requests to EC2 instances through HTTP (80), with IIS hosting a .net webapi application, using swashbuckle to describe the API methods.
Home page of the API (https://example.com) has a link to Swagger documentation which can bee read as https://example.com/swagger/ui/index.html when you hove over on the link.
If I click on the link it redirects the request on the browser to http://example.com/swagger/ui/index.html which displays a Page Not Found error
but if I type directly in the browser URL https://example.com/swagger/ui/index.html then it loads Swagger page, but then, when expanding the methods an click on "Try it out", the Request URL starts with "http" again.
This configuration is only for Stage and Production environments. Lower environments don't use the load balancer and just use http.
Any ideas on how to stop https being redirected to http? And how make swagger to display Request URLs using https?
Thank you
EDIT:
I'm using a custom index.html file
Seems is a known issue for Swashbuckle. Quote:
"By default, the service root url is inferred from the request used to access the docs. However, there may be situations (e.g. proxy and load-balanced environments) where this does not resolve correctly. You can workaround this by providing your own code to determine the root URL."
What I did was provide the root url and/or scheme to use based on the environment
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
...
c.RootUrl(req => GetRootUrlFromAppConfig(req));
...
c.Schemes(GetEnvironmentScheme());
...
})
.EnableSwaggerUi(c =>
{
...
});
where
public static string[] GetEnvironmentScheme()
{
...
}
public static string GetRootUrlFromAppConfig(HttpRequestMessage request)
{
...
}
The way I would probably do it is having a main file, and generating during the build of your application a different swagger file based on the environnement parameters for schemes and hosts.
That way, you have to manage only one swagger file accross your environments, and you only have to manage a few extra environnement properties, host and schemes (if you don't already have them)
Since I don't know about swashbuckle, I cannot answer for sure at your first question (the redirect)

WebAPI SignalR Negotiate response different on different browsers

The main problem about Access-Control-Allow-Origin I think. But when I configure the Web API project as defined in the given documentation, it still not working in chrome and firefox but working in IE well (it is about IE thinks localhost is not cross domain, AFAIK). I tried different ways to make it work but no result.
I put the example project to github repository. Project is very simple. There are two applications working on cross domains. It is very simple chat application like in signalr examples.
You must change the value of api host in client javascript file:
https://github.com/yusufuzun/WebApiSignalR/blob/master/ChatApp/Scripts/app/chat.js#L2
When you open the Chat page in mvc project, there will be two requests to api application
1- Regular ajax request (which is working fine)
2- Signalr negotiate request (cancelled)
And also I don't think browser disables the CORS because of if it disables there would not be an hit to server. So I think it is about browser but not about browser disables (something else).
Details are in repository
Readme: https://github.com/yusufuzun/WebApiSignalR/blob/master/README.md
Fiddler Results: https://github.com/yusufuzun/WebApiSignalR/blob/master/FiddlerResults
The bad part about it also is server returning 500 with this error:
System.InvalidOperationException: 'chat' Hub could not be resolved.
Which hub name is chat also.
https://github.com/yusufuzun/WebApiSignalR/blob/master/ChatApi/Hubs/ChatHub.cs#L10
You can enable CORS for Web Api in project with different ways for test purposes. Each one is giving different errors all about XMLHttpRequest Access-Control-Allow-Origin.
I commented them, so you can uncomment and make test for each one:
https://github.com/yusufuzun/WebApiSignalR/blob/master/ChatApi/Global.asax.cs#L24
https://github.com/yusufuzun/WebApiSignalR/blob/master/ChatApi/App_Start/WebApiConfig.cs#L14
https://github.com/yusufuzun/WebApiSignalR/blob/master/ChatApi/App_Start/WebApiConfig.cs#L16
https://github.com/yusufuzun/WebApiSignalR/blob/master/ChatApi/Controllers/ChatController.cs#L17
So what is going on here?
After I talked with David Fowler in JabbR, he mentioned the thing about using CORS with SignalR. My signalr startup code was wrong. So after changing the startup code like in his advice it worked well.
He also mentioned SignalR and Web API are working with different CORS definitions. So enabling or disabling one doesn't affect other.
Here is the new startup code:
app.Map("/signalr", map =>
{
map.UseCors(CorsOptions.AllowAll);
map.RunSignalR(new HubConfiguration()
{
EnableDetailedErrors = true,
EnableJavaScriptProxies = true
});
});
The old one:
app.MapSignalR(new HubConfiguration()
{
EnableDetailedErrors = true,
EnableJavaScriptProxies = true
}).UseCors(CorsOptions.AllowAll);
Hope it helps to somebody out there.

ASP.NET Web API: How do you read server variables in a Web API controller?

How would you read the following server variables in an ASP.NET Web API controller?
HTTP_HOST
SERVER_NAME
REMOTE_HOST / REMOTE_ADDR
I see a System.Net.Http.HttpRequestMessage Request defined, but I don't see a collection containing these variables.
I'm running a website on a single IP with multiple host headers and I need to determine which site they used to get there.
EDIT:
It ended up being something like this:
((System.Web.HttpContextWrapper) Request.Properties["MS_HttpContext"])
.Request.ServerVariables["HTTP_HOST"]
The information you are looking for is dependent on the host you are using and Web API is designed to be host independent. So.... the information you are looking for will be buried in the httpRequestMessage.Properties collection and it will be different depending on your host.
If you move to using the Owin adapter then you will get a standardized Owin environment object.
I was able to all that information from the RequestUri within Request
Request.RequestUri.Scheme + Uri.SchemeDelimiter +
Request.RequestUri.Host + (Request.RequestUri.IsDefaultPort ? string.Empty : (string.Concat(":", Request.RequestUri.Port)))

Resources