Override host of webapi odata links

后端 未结 6 1746
Happy的楠姐
Happy的楠姐 2020-12-06 19:55

I\'m using WebAPI 2.2 and Microsoft.AspNet.OData 5.7.0 to create an OData service that supports paging.

When hosted in the production environment, the WebAPI lives o

6条回答
  •  庸人自扰
    2020-12-06 20:33

    The answer by lencharest is promising, but I found an improvement on his method. Rather than using the UrlHelper, I created a class derived from System.Net.Http.DelegatingHandler. This class is inserted (first) into the message handling pipeline and thus has a crack at altering the incoming HttpRequestMessage. It's an improvement over the above solution because in addition to altering the controller-specific URLs (as the UrlHelper does, e,g, https://data.contoso.com/odata/MyController), it also alters the url that appears as the xml:base in the OData service document (e.g., https://data.contoso.com/odata).

    My particular application was to host an OData service behind a proxy server, and I wanted all the URLs presented by the server to be the externally-visible URLs, not the internally-visible ones. And, I didn't want to have to rely on annotations for this; I wanted it to be fully automatic.

    The message handler looks like this:

        public class BehindProxyMessageHandler : DelegatingHandler
        {
            protected async override Task SendAsync(
                HttpRequestMessage request, CancellationToken cancellationToken)
            {
                var builder = new UriBuilder(request.RequestUri);
                var visibleHost = builder.Host;
                var visibleScheme = builder.Scheme;
                var visiblePort = builder.Port;
    
                if (request.Headers.Contains("X-Forwarded-Host"))
                {
                    string[] forwardedHosts = request.Headers.GetValues("X-Forwarded-Host").First().Split(new char[] { ',' });
                    visibleHost = forwardedHosts[0].Trim();
                }
    
                if (request.Headers.Contains("X-Forwarded-Proto"))
                {
                    visibleScheme = request.Headers.GetValues("X-Forwarded-Proto").First();
                }
    
                if (request.Headers.Contains("X-Forwarded-Port"))
                {
                    try
                    {
                        visiblePort = int.Parse(request.Headers.GetValues("X-Forwarded-Port").First());
                    }
                    catch (Exception)
                    { }
                }
    
                builder.Host = visibleHost;
                builder.Scheme = visibleScheme;
                builder.Port = visiblePort;
    
                request.RequestUri = builder.Uri;
                var response = await base.SendAsync(request, cancellationToken);
                return response;
            }
        }
    

    You wire the handler up in WebApiConfig.cs:

        config.Routes.MapODataServiceRoute(
            routeName: "odata",
            routePrefix: "odata",
            model: builder.GetEdmModel(),
            pathHandler: new DefaultODataPathHandler(),
            routingConventions: ODataRoutingConventions.CreateDefault()
        );
        config.MessageHandlers.Insert(0, new BehindProxyMessageHandler());
    

提交回复
热议问题