I have an Owin Startup class that registers a WebApi controller action and hooks it in using IAppBuilder.UseWebApi. My route templates is /api/packages/{id}/{version} where version may contain periods (as in 1.0.0).
This works fine with self hosting, but when I try to run my code in IIS using Microsoft.Owin.Host.SystemWeb, something is preventing my action from being invoked when the path looks like a static content request.
For example, GET /api/packages/Foo/1.0 works on self host but results in a 404 on IIS.
If I add a trailing slash as in GET /api/packages/Foo/1.0/ it works in both self host and IIS.
It seems that something in the UseWebApi method is preventing Web Api from handling requests that look like files with extensions.
Other Owin middleware sees all of these requests, so I know the request is getting into the Owin pipeline, but then something about the UseWebApi method seems to be ignoring some requests.
Related: Owin Middleware results in 404 on server, Owin hosted on IIS doesn't capture URLs with Dot "."
After further debugging, I was mapping another OWIN middleware for SignalR before wiring in WebApi, and the order seems to matter on Web-Host but not on Self-Host. Changing the order resolved this issue for me.
Update: When using Owin.Host.SystemWeb, IAppBuilder.UseStageMarker(PipelineStage.MapHandler) should be invoked after any middleware that wish to handle requests that appear to be for static content.
See https://katanaproject.codeplex.com/wikipage?title=Static%20Files%20on%20IIS and http://www.asp.net/aspnet/overview/owin-and-katana/owin-middleware-in-the-iis-integrated-pipeline.
Related
Update
I have found, that the configuration is "correct", in that the application gateway properly routes to the correct backend when using the "/payment" path. On the app in question however, the path is still "/payment" which obviously does not work. I know I can circumvent this by using Override Backend Path to "/", but then, as said, the app does not load any CSS / JS files because it looks on the root of the host (I think)
I have a setup going with Azure Application Gateway for a project I am working on currently.
Setup
The basic setup goes like this:
Public IP --> Appliction Gateway --> Private Endpoints --> WebApps.
I have enabled multi-site hosting, have given an Azure domain (.cloudapp.azure.com) and have enabled path based routing.
So for example mydomain.germanywestcentral.cloudapp.azure.com/payment will route to a certain backend.
Issue
The issue is, while the HTML is loading just fine, all the CSS/JS is not looking at
"mydomain.germanywestcentral.cloudapp.azure.com/payment/site/style.css"
but at
"mydomain.germanywestcentral.cloudapp.azure.com/site/style.css"
I already googled for hours how to solve this issue but to no avail. I realize Azuer is one of the lesser used clouds as of now, but hopefully someone here can, at least in concept, explain what is happening and what needs to be done. Any pointers are helpful here :)
Disclaimer
I am rather new to the whole networking topic and Azure, so I am not sure how to solve this issue. How do I tell the app to not look at the root, but at the /payment. If I go to "mydomain.germanywestcentral.cloudapp.azure.com/site/style.css" it loads the file just fine.
Note
One thing: In order for any of this to work, I had to set "Override Backend Path" to "/", which is probably what is causing the issue.
However, if I turn this off, it does not load anything, and instead fails loading the site altogether.
Images of the settings
HTTP Setting for Payment Backend
Listener Configuration
Rule Configuration
We are using azure application gateway to route requests from host/client to the specific client app (.NET Core). This way client1 is routed to server1/client1 and client2 is routed to server2/client2 and so on. We are using URL path map to resolve the exact server for each client.
Application gateway has a limitation in 100 paths in URL Path map per listener. This forces us to keep the number of client applications low.
Recently we have rewritten our application to support multiple tenants. So now we can process multiple clients' requests using a single app. Our new routing looks like server/app/client. Still, we want to keep end-clients URLs in the same way as those are: host/client
My idea was next: Use Application gateway rewrite set, and on request, replace URL path values from /client to /app/client; But it seems that no matter what I set into those rules I do I keep getting the same response. It looks to me that rewrite rules are simply ignored. Even the basic one that does not contain any if logic.
e.g.:
-
So my question is whether it is possible to update request URL before application gateway rules are applied?
Will be really glad to get some help here.
Don't know if you solved your problem but I had exactly the same !
It looks like Microsoft made some changes few days ago on Application Gateway. And now it works ! But I had to delete my Application Gateway and create it again from scratch.
Hope this will help
Denis
I have a project, It's a web application that requires Windows Authentication.
I've setup an Active Directory at home using my NAS virtualization. Then I've created a VMWare Server for IIS which is a member of that domain on my desktop which I also use for development. I've created the Web API and installed it into that VMWare server. When I call a routine directly, it works and return results but when I use the Web API routine from my javascript web application I keep on getting 401 error. I then put the code on the IIS server and the web application works.
I've seen a lot of solutions like changing the sequence of the Provider in IIS Authentication. Added Everyone read/write permission on the folders. I've also added entry on the web.config. But none of them work.
*****Update as per request on the comment *****
Below is when I run directly from Web API
Calling the Web API from Javascript
Here's the error I'm getting
Just FYI, I tried running the web api from Visual Studio on the same machine but also with 401 error
Is there anything I could add to AD to make my development machine as trusted?
********************A new issue after the code change **********
****************Another Update******
This is definitely weird, so I installed Fiddler 4 to see what's going on. But still no luck.
Then I made changes on the IIS HTTP Response Header
The weird thing is when I run Fiddler the error is gone but when I close it it comes back.
There are two things going on here:
A 401 response is a normal first step to Windows Authentication. The client is then expected to resend the request with credentials. AJAX requests don't do this automatically unless you tell it to.
To tell it to send credentials in a cross-domain request (more on that later), you need to set the withCredentials option when you make the request in JavaScript.
With jQuery, that looks like this:
$.ajax({
url: url,
xhrFields: {
withCredentials: true
}
}).then(callback);
These problems pop up when the URL in the address bar of the browser is different than the URL of the API you are trying to connect to in the JavaScript. Browsers are very picky about when this is allowed. These are called "cross-domain requests", or "Cross-Origin Resource Sharing" (CORS).
It looks at the protocol, domain name and port. So if the website is http://localhost:8000, and it's making an AJAX request to http://localhost:8001, that is still considered a cross-domain request.
When a cross-domain AJAX request is made, the browser first sends an OPTIONS request to the URL, which contains the URL of the website that's making the request (e.g. http://localhost:8000). The API is expected to return a response with an Access-Control-Allow-Origin header that says whether the website making the request is allowed to.
If you are not planning on sending credentials, then the Access-Control-Allow-Origin header can be *, meaning that the API allows anyone to call it.
However, if you need to send credentials, like you do, you cannot use *. The Access-Control-Allow-Origin header must specifically contain the domain (and port) of your webpage, and the Access-Control-Allow-Credentials must be set to true. For example:
Access-Control-Allow-Origin: http://localhost:8000
Access-Control-Allow-Credentials: true
It's a bit of a pain in the butt, yes. But it's necessary for security.
You can read more about CORS here: Cross-Origin Resource Sharing (CORS)
I want to use a reverse proxy to point one of my endpoints to a resource that's hosted elsewhere. My primary server (where everything else is hosted) is in an Azure Web App and is otherwise working perfectly.
I've been using this seemingly failproof article along with the other links mentioned at the bottom of it: https://blogs.msdn.microsoft.com/zhiliang_xus_blog/2016/01/19/build-a-google-reverse-proxy-site-on-azure-web-app-in-less-than-3-minutes/
As a baseline, I used a Web App with no additional code and confirmed that the reverse proxy works. This was done by manually creating/editing the web.config file and applicationHost.xdt file then restarting the server.
I've tried 3 separate approaches (all on clean, new web apps) all of which are failing for me:
Push my code, confirm it works, then follow the reverse proxy steps manually
Follow the steps manually, confirm reverse proxy works, then push my code
Put the reverse proxy files into my codebase and push everything at the same time
None of these 3 approaches are working. Is this a bug in Azure? How can I try to figure this out?
Post XML Transformation (XDT), have you restarted the site?
I would suggest you to take a look at this blog from Ruslan:
http://ruslany.net/2014/05/using-azure-web-site-as-a-reverse-proxy/
It talks about using a Site extension. It implements the reverse proxy and it does the XDT transformation for you.
If the above is setup correctly, then there is something wrong with the URL Rewrite rules. I would recommend you to enable Failed Request Tracing and debug this further.
The link/way you posted used URL Rewrite to implement a reverse proxy. I tested it and it worked fine with my empty web application. After published a web application to the Azure Web App(For example, an ASP.NET MVC web application), the URL Rewrite stopped working. The reason is that all the requests to your web application are routed by ASP.NET route module.
To enable URL Rewrite for some URLs, we need to disable ASP.NET route for these URLs. For example, if you want to rewrite all the requests with "product/xxx" format to another site. You could add following code to RouteConfig.cs file.
routes.Ignore("product/{action}");
The problem in this specific case was the location of my web.config file.
It needs to be in the root directory of the application which, in my case, was not site\wwwroot. My code was being generated and copied into site\wwwroot\dist. Putting the config file in that directory fixed the problem.
Additionally, there are logs that can be enabled to get some insight as to what's going on: https://learn.microsoft.com/en-us/azure/app-service-web/web-sites-enable-diagnostic-log
I'm working with MicroStrategy 10.3, hosted on IIS 7.5. I'm using their
URL API to run a document, and change the value of a drop down selector.
IIS is tinkering with my query parameters though, via a 302 redirect. This URL:
https://server/MicroStrategy/asp/Main.aspx?Server=XXX&Project=XXX&evt=2048001&src=Main.aspx.2048001&maxWait=-1&documentID=XXX&evt=2048084&src=Main.aspx.oivm.rwb.2048084&ctlKey=XXX&elemList=hXX;XXX&evtorder=2048001%2c2048084&2048084=1&2048001=1
is being 302'ed to:
https://server/MicroStrategy/asp/Main.aspx?Server=XXX&Project=XXX&evt=2048001%2C2048084&src=Main.aspx.2048001%2CMain.aspx.oivm.rwb.2048084&maxWait=-1&documentID=XXX&ctlKey=XXX&elemList=hXX%3BXXX&evtorder=2048001%2C2048084&2048084=1&2048001=1
(The two distinct evt and src are being combined, and MicroStrategy is complaining that 'Event ID 2048001,2048084 is illegal'.)
Does IIS do this type of thing out of the box? It certainly seems unlikely. I can't see any custom HTTP redirects in IIS Manager for the application.
IIS was most definitely not the culprit.
MicroStrategy was generating the 302 redirect itself, subsequent to an automated login. You would think that an enterprise application wouldn't rewrite its own URL such that it causes an error, but you'd be wrong.
I resolved the issue by manually adding a login event, and URL-encoding the two events I wanted to call into the target key:
https://server/MicroStrategy/asp/Main.aspx?Server=XXX&Project=XXX&evt=3054&src=Main.aspx.3054&target=evt%3D2048001%26src%3DMain.aspx.2048001%26maxWait%3D-1%26documentID%3DXXX%26evt%3D2048084%26src%3DMain.aspx.oivm.rwb.2048084%26ctlKey%3DXXX%26elemList%3DhXX%3BXXX%26evtorder%3D2048001%252c2048084%262048084%3D1%262048001%3D1